I am trying to implement an event calendar inside one of my vue components in Laravel but I am not able to display the events on the calendar from my SQL database. Although, I am able to view the columns of my table using my resource controller.
Note:- I am using router-view to display all the content under the id content so there are no blade templates.
Any help please!!
Thanks in advance.
Dashboard.vue
<template>
<full-calendar :config='config'>
</full-calendar>
</template>
<script>
export default{
data() {
return {
config: {
defaultView: "month"
},
methods:{
loadEvents() {
axios.get("api/event").then(({ data }) => (this.events = data));
}
},
created(){
this.loadEvents();
}
};
</script>
Controller type:resource
public function index()
{
$events = DB::table('events')->get();
$event = [];
foreach($events as $row){
$endDate = $row->end_date."24:00:00";
$event[] = \Calendar::event(
$row->event_title,
true,
new \DateTime($row->start_date),
new \DateTime($row->end_date),
$row->id,
[
'color'=>$row->color,
]
);
}
$calendar = \Calendar::addEvents($event);
return $events;
}
class CreateEventsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('events', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->string('event_title');
$table->string('event_description');
$table->string('color');
$table->datetime('start_date');
$table->datetime('end_date');
$table->timestamps();
});
}
};
Related
there is a way to listen the laravel livewire lifecycle hooks? for example...
in php is:
public function updatedFoo($value)
{
//
}
how it can be in js (i know use #this generate the id finder)?
window.Livewire.find('componentIdGenerated').on('updatedFoo', function(value) {
//
});
thanks a lot!
It's possible and really cool. As the documentation tells, there is JavaScript hooks related like
<script>
document.addEventListener("DOMContentLoaded", () => {
....
Livewire.hook('message.sent', (message, component) => {})
Livewire.hook('message.failed', (message, component) => {})
Livewire.hook('message.received', (message, component) => {})
Livewire.hook('message.processed', (message, component) => {})
});
</script>
Let's say, you make some call to some method and using this you can get messages hooks and do proper operations
<script>
document.addEventListener("DOMContentLoaded", () => {
Livewire.hook('message.sent', (message,component) => {
if (message.updateQueue[0].payload.method === 'openModal') {
// message was sent
}
Livewire.hook('message.received', (message,component) => {
if (message.updateQueue[0].payload.method === 'openModal') {
// message was received
}
// and go on!
</script>
also you can listen when an event occurs and do the same
<script>
document.addEventListener("DOMContentLoaded", () => {
Livewire.hook('message.sent', (message,component) => {
if (message.updateQueue[0].payload.event === 'someDispatchedEvent') {
// message was sent
}
Livewire.hook('message.received', (message,component) => {
if (message.updateQueue[0].payload.event === 'someDispatchedEvent') {
// message was received
}
// and go on!
</script>
hope you can exploit this more and show us how you go! ;-)
thanks to #Prospero for give the first steps and the general idea about the necesary code
first we need to save the initial state of our property (in my case is a modal component, the id is dynamic):
The variables in brackets are blade variables)
...
#php
$id = $id ?? \Illuminate\Support\Str::random(15);
$model = $attributes->wire('model')->value()
#endphp
...
<script wire:ignore>
var model{{ $id }};
document.addEventListener("livewire:load", function(event) {
model{{ $id }} = #this.{{ $model }};
});
</script>
then, with the livewire hooks, you have to listen the element.updated event, and compare the initial state with the new state of the livewire property
i use only conditional comparisons, i saw you can use Proxy for clean code:
<script wire:ignore>
document.addEventListener("DOMContentLoaded", () => {
Livewire.hook('element.updated', (el, component) => {
if(model{{ $id }} && !#this.{{ $model }})
new bootstrap.Modal(document.getElementById('{{ $id }}')).hide();
if(!model{{ $id }} && #this.{{ $model }})
new bootstrap.Modal(document.getElementById('{{ $id }}')).show();
model{{ $id }} = #this.{{ $model }};
});
});
</script>
I use this for open a bootstrap modal blade component component.
I am migrating my current application from Laravel Livewire to Laravel InertiaJS VueJS. Currently I am stuck at setting the per page count from the front end and paginate the data accordingly. Currently I am using Laravel's default pagination along with the custom pagination component for VueJS and it works seamlessly. I just want to set the $per_page as per the input, the variable is set to 5 by default, in the index method of the controller. Below is the code structure and the logic. Please help me achieve this in the way InertiaJS is meant to be used.
UserController.php
public function index(Request $request)
{
$per_page = \Request::get('per_page') ?: 5;
$query = User::select('id', 'name', 'email', 'role_id', 'created_at');
$users = $query->paginate($per_page);
return Inertia::render('Backend/Management/AudienceManagement/Users/Index', [
'users' => $users
]);
}
Users/Index.vue
<template>
<input-group borderless paddingless inline>
<input-select #change="setPerPage($event)" id="perPage" placeholder="Per Page">
<option value="5">5</option>
<option value="10">10</option>
</input-select>
</input-group>
</template>
<script>
import {
Inertia
} from '#inertiajs/inertia'
export default {
props: {
users: {
type: Object
}
},
data() {
return {
sortField: '',
sortDirection: ''
}
},
methods: {
setPerPage(event) {
console.log(event.target.value);
this.users.per_page = event.target.value;
Inertia.reload({
only: ['users.data']
});
},
}
}
</script>
I'm trying to build a simple website builder that allow users to save their generated html created with Vue component and see it at a certain URL.
Because of it I have to store and retrieve the html generated but I have some problems with retrieving of the code. Here is my step:
When user click "save" this function is fired, that select the portion of HTML that include the "website" built by the user:
saveBuilders: function () {
let pages = [];
let builders = $('[id*="builder-container-"]');
$.each(builders, function (key, builder) {
let singleElem = $(builder).attr('id');
pages.push(clearElement.html());
});
this.storeInDb(pages);
},
storeInDb: function (pagesList) {
axios.post("/landing-page/store", {
name: this.name,
description: this.description,
html: pagesList
})
.then(function (response) {
console.log('Cool');
})
.catch(function (error) {
console.log('ERROR', error.response);
});
},
The Axios request is handled by this function that store the html portion in DB
public function store(Request $request)
{
$data = $request->all();
$html = $data['html'];
$landingPage = new LandingPage();
$landingPage->name = $data['name'];
$landingPage->description = $data['description'];
$landingPage->user_id = Auth::user()->id;
$landingPage->html = json_encode($html);
try {
$landingPage->save();
return 'true';
} catch (exception $e) {
return $e;
}
}
Now when the user visit a certain URL, for keep thing simple suppose is example.it/website/0, this function is fired:
public function show($landing_id)
{
try {
$landingPage = LandingPage::where([
'id' => $landing_id,
'user_id' => Auth::user()->id
])->first();
} catch (\Exception $e) {
$landingPage = null;
}
if ($landingPage != null) {
//GET THE HTML
$page = json_decode($landingPage->html);
return view('landing_page.show')->with('page', $page)
} else {
abort(404, 'Error');
}
}
And this the blade where I'm trying to re-create the Vue.js environment
<body>
<span id="countdown"></span>
<div id="builder-pagina">
<builder>
{!! $page !!}}
</builder>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="{{asset('js/landing_page/app.js')}}"></script>
</body>
</html>
I thought that having the html generated by vue similar to something like that into the DB...
<div data-v-29b64d26="" >
<h1>This piece of code was stored into my DB</h1>
<div data-v-56f62f0a="">
</div>
</div>
...you could create everything working simply by pasting the code and by using the same js file used for compiling vue.js.
I've tried pass the entire code by props but is not working. Also tried with slot. Any suggestions?
i have problem. When I click the button, it receives an entire database, but I want laod part database. How can I do this?
For example: After every click I would like to read 10 posts.
Thx for help.
Messages.vue:
<div class="chat__messages" ref="messages">
<chat-message v-for="message in messages" :key="message.id" :message="message"></chat-message>
<button class="btn btn-primary form-control loadmorebutton" #click="handleButton">Load more</button>
</div>
export default{
data(){
return {
messages: []
}
},
methods: {
removeMessage(id){...},
handleButton: function () {
axios.get('chat/messagesmore').then((response) => {
this.messages = response.data;
});
}
},
mounted(){
axios.get('chat/messages').then((response) => {
this.messages = response.data
});
Bus.$on('messages.added', (message) => {
this.messages.unshift(message);
//more code
}).$on('messages.removed', (message) => {
this.removeMessage(message.id);
});
}
}
Controller:
public function index()
{
$messages = Message::with('user')->latest()->limit(20)->get();
return response()->json($messages, 200);
}
public function loadmore()
{
$messages = Message::with('user')->latest()->get();
// $messages = Message::with('user')->latest()->paginate(10)->getCollection();
return response()->json($messages, 200);
}
paginate(10) Loads only 10 posts
You can do it like this:
<div class="chat__messages" ref="messages">
<chat-message v-for="message in messages" :key="message.id" :message="message"></chat-message>
<button class="btn btn-primary form-control loadmorebutton" #click="handleButton">Load more</button>
</div>
export default{
data(){
return {
messages: [],
moreMessages: [],
moreMsgFetched: false
}
},
methods: {
removeMessage(id){...},
handleButton: function () {
if(!this.moreMsgFetched){
axios.get('chat/messagesmore').then((response) => {
this.moreMessages = response.data;
this.messages = this.moreMessages.splice(0, 10);
this.moreMsgFetched = true;
});
}
var nextMsgs = this.moreMessages.splice(0, 10);
//if you want to replace the messages array every time with 10 more messages
this.messages = nextMsgs
//if you wnt to add 10 more messages to messages array
this.messages.push(nextMsgs);
}
},
mounted(){
axios.get('chat/messages').then((response) => {
this.messages = response.data
});
Bus.$on('messages.added', (message) => {
this.messages.unshift(message);
//more code
}).$on('messages.removed', (message) => {
this.removeMessage(message.id);
});
}
}
-initialize a data property morMsgFetched set to false to indicate if more messages are fetched or not
if morMsgFetched is false make the axios request and st the response to moreMessages, then remove 10 from moreMessages and set it to messages[]..
After that set morMsgFetched to true
on subsequest click remove 10 from moreMessages and push it to 'messages[]`
Use Laravels built in pagination.
public function index()
{
return Message::with('user')->latest()->paginate(20);
}
It returns you next_page url which you can use to get more results calculated automatically
This might be too late but i believe the best way to do it is using pagination, Initially onMounted you'll send a request to let's say /posts?page=1, the one is a variable let's say named 'pageNumber', each time the user clicks on the "Load More" button, you'll increment the pageNumber and resent the request, the link will page /posts?page=2 this time, at this point you can append the results you've got to the already existing one and decide if the Load More button should be shown based on the last_page attribute returned by laravel paginator...
I'm sure you already solved your problem or found another alternative, this might be usefull for future developers.
am trying to retrieve data from a database using vuejs ajax call with a plugin called vue-resource. Unfortunately, the json data object contains the html page and not the actual data from the database. Can someone please tell me what am doing wrong?
This is my code:
routes.php
<?php
Route::get('find', 'FruitsCtrl#index');
fruitsctrl.php (controller)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Fruit;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class FruitsCtrl extends Controller
{
public function index(Request $req){
$fruits = Fruit::all();
return view('fruitsHome', $fruits);
}
}
fruit.php (model)
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Fruit extends Model
{
protected $fillable = [
'id', 'name', 'type'
];
}
fruitshome.blade.php (view)
<head>
<meta id="token" content="{{ csrf_token() }}">
</head>
<body>
<div class="row" id="vapp">
<ul>
<li v-for="fruit in fruits">
#{{ fruit.name }}
#{{ fruit.type }}
</li>
</ul>
</div>
<body>
app.js (javascript)
Vue.http.headers.common['X-CSRF-TOKEN'] = document.querySelector('#token').getAttribute('content');
var v = new Vue({
el : "#vapp",
ready :function () {
this.fetchFruits();
},
data : {
fruit : {id:'', name:'', type:''},
fruits : []
},
methods : {
fetchFruits : function(){
this.$http.get('/find').then(function(res){
this.fruits = res;
},function (data){
console.log(error ...);
});
}
}
});
You're currently returning a view from your controller:
class FruitsCtrl extends Controller
{
public function index(Request $req){
$fruits = Fruit::all();
return view('fruitsHome', $fruits);
}
}
Instead, you can return the Eloquent results directly and they'll be output as JSON:
class FruitsCtrl extends Controller
{
public function index(Request $req){
$fruits = Fruit::all();
return $fruits;
}
}
I think you need to set table name in the model like this :
class Fruit extends Model
{
protected $table = 'fruits';
protected $fillable = [
'id', 'name', 'type'
];
}
You also need to update index method like this :
public function index(Request $req){
$fruits = Fruit::all();
return view('fruitsHome')->withFruits($fruits);
}
and finally update the blade :
<li v-for="fruits in fruit">
#{!! $fruits->name !!}
#{!! $fruits->type !!}
</li>
Let me know if it helps you