Laravel 8 Jquery drag and drop list and update to database – Livewire
Hey learner, Today I am gonna show you how we can use Jquery drag and drop list and update to database with Livewire.
We will also update the drag and drop order to our database using livewire events.
Actually I have tried the livewire/sortable package first, but I didn’t find that useful for my situation. So, I turned back to jquery UI sortable.
Anyway, let’s get started.
I assume that you have already set up your Laravel and Livewire project. So, I am not going to show that process. Just get straight to the point.
Create Livewire component
Create a new Livewire component with name DraggableList by using following command
php artisan make:livewire DraggableList
It will create the livewire component class file in the app/Http/livewire directory. One more file it will add that will be a laravel blade file in the resources/views/livewire directory.
Well done, we are ready to perform the action. Add the jquery file in the head or footer if not added yet.
Now, our job will be divided into two parts: one is to integrate the jquery ui sortable with our html and another is to update the dragged position to our database. Wait, I think we will also need to update the order when we delete something from our list.
Ok, we will cover that too.
Prepare livewire component
So, let’s start with the Livewire part first. As we can see we have a render method here in our component file. This method enables us to interact with our laravel blade file as a view part for this component. Now let’s add the mount method it will call before our component is mounted or initialized.
<?php namespace App\Http\Livewire; use App\Models\Lists; use Livewire\Component; class DraggableList extends Component { public $list = []; protected $listeners = ["updateComponent" => "updateComponent", "ListOrderUpdated" => "ListOrderUpdated"]; public function mount() { $this->updateComponent(); } public function render() { return view('livewire.draggable-list'); } public function deleteListItem( $id ) { $this->dispatchBrowserEvent("deletingEvent", ['id' => $id, 'type' => 'list']); Lists::find($id)->delete(); } public function cloneListItem( $id ) { $list = Lists::find($id)->replicate(); $list->position = (Lists::max("position")+1); $list->save(); $this->updateComponent(); } public function updateComponent() { $this->list = Lists::orderBy('position')->get(); } public function ListOrderUpdated( $orderData ) { foreach ($orderData['lists'] as $id => $position) { if ($this->betweenRange($position, $orderData['min'], $orderData['max'])) { Lists::where('id', $id)->update([ 'position' => $position ]); } } $this->updateComponent(); } protected function betweenRange($number, $min, $max) { return ($number >= $min && $number <= $max); } }
Through the updateComponent method we will update our list, whenever we need it to update.
We will emit the livewire event after getting an update from jquery ui sortable. When deleting the list item we will again emit that event to update the order too.
<div> <div class="container d-flex align-items-center justify-content-center vh-100"> <div class="list-group w-50 sortable"> @foreach ($list as $item) <a href="#" data-list-id="{{$item['id']}}" data-list-position="{{$item['position']}}" class="list-group-item list-group-item-action list-group-item-primary d-flex align-items-center justify-content-between my-1 ui-sortable-handle"> <i class="fas fa-arrows-alt handler"></i> <span>Id: {{ $item['id'] }}</span> <span>{{ $item['name'] }}</span> <span> Position: {{ $item['position'] }}</span> <i class="fas fa-clone" wire:click='cloneListItem({{$item["id"]}})'></i> <i class="fas fa-trash" wire:click='deleteListItem({{$item["id"]}})'></i> </a> @endforeach </div> </div> @include('inc.loader') </div>
Update sorted order to the database
Bonus point, We will update only those records which actually affect after this sort. It will save our requests to the database. Like if we drag the 123rd item to 112th item then we will update only 112 to 123 items.
For this purpose we are already passing positions to our list item. Now when we drag the 123rd item and drop over 112th item, we have got two points.
Let’s take the 123rd as current position and 112th as target position. After getting the min and max, we will get min = 112 and max = 123.
So, the logic will be something like this. If the position is in between the min and max then it needs to update to the database otherwise no need to update it to the database. By this way we will ignore other items to be updated.
JQuery UI sortable to create Jquery drag and drop list
<script> $(document).ready(function() { $('.sortable').sortable({ //axis: "y", //handle: ".handler", items: ".ui-sortable-handle", cursor: 'move', opacity: 0.6, update: function(event, ui) { updateOrderOnServer(ui.item, '.ui-sortable-handle', 'list'); } }) }) window.addEventListener('deletingEvent', event => { deletingItem(event.detail.id, event.detail.type); }); function deletingItem( id, type ) { const deletedItem = $(`[data-${type}-id='${id}']`); console.log('next field after delete', deletedItem.next()); const item = deletedItem.next(); deletedItem.remove(); if (item.length > 0) { const itemClass = ".ui-sortable-handle"; updateOrderOnServer(item, itemClass, type, 'delete'); } else { //window.livewire.emit("updateComponent"); } } function updateOrderOnServer(item, itemClass, type, action = 'order') { var orderData = { [`${type}s`]: {} }; var current = $(item).data(`${type}-position`); var target = 0; var items = $(item).parent().find(itemClass); items.each(function(index, element) { console.log(index, element); var id = $(element).data(`${type}-id`); orderData[`${type}s`][id] = index+1; if ($(item).data(`${type}-id`) === id) { target = index+1; } }) orderData['min'] = Math.min(current, target); if ( action==='delete' ) { orderData['max'] = items.length; } else { orderData['max'] = Math.max(current, target); } if ( items.length > 0 ) { console.log(orderData); window.livewire.emit("ListOrderUpdated", orderData); } } </script>
That’s it, this is the tutorial about Jquery drag and drop list and update to database with livewire. If you have any query let me know in the comment section below.