Drag-and-Drop Overview0:00
Whenever you have a collection of things that you need to put in some sort of order, a drag and drop UI is usually the best way to accomplish this. Now, there are several drag and drop JavaScript libraries available, but if you want to persist this order to the database, you need to do some extra work, set up some endpoints, and update the backend. Now, I personally think this is another great use case for using Livewire to simplify everything. In fact, Livewire does come with a plugin to make this process pretty seamless. So let's see if we can make use of this so we can drag and drop our list of songs here. So we do have an order field on the songs, which I am currently sorting by. Take a look at the database. You'll see I'm sorting by the order field, and you can see this order is the same as being shown in the browser. So 312654. And if you take a look at our routes file here, I am ordering by that order.
Move Table to Livewire0:36
see I'm sorting by the order field, and you can see this order is the same as being shown in the browser. So 312654. And if you take a look at our routes file here, I am ordering by that order field here before passing it to our Blade view called drag-drop. And of course, we're just displaying it in our table here. So our first step is to move this to a Livewire component. So let's go ahead and do that. So I'll grab the entire table. Let's cut that out. Let's make a new Livewire component. Let's name it DragDropSongs. Okay, let's go ahead and make that component php artisan Livewire:make DragDropSongs. Okay, let's go into that Livewire component, DragDropSongs. And it's based in our table here. Okay, save that. And now we no longer have access to our songs here. So we can either pass it in here, or we can just move that logic to our Livewire class. Let's take that approach. So let's open the class up. So DragDropSongs.
Install Sortable Plugin1:31
to our songs here. So we can either pass it in here, or we can just move that logic to our Livewire class. Let's take that approach. So let's open the class up. So drag drop songs. And let's just pass in our songs here as a param after we return the view. So pretty much what we have in our controller, or in this case, our Rust file. So let's grab all of this, we no longer need to pass anything here. Save this, go back here. And let's pass that in here. Make sure to import Song here. Let's save that and everything should be the same. Back here, refresh. And everything is still the same. But now it's within a Livewire component. So now let's make use of this plugin here. So under the hood, it's making use of Shopify's sortable package, which does have some drawbacks, which we'll address later on. But for now, let's install it using the CDN here. So we'll copy this. And let's go back to our Blade view. And I do have a stack for our scripts. So let's add that down.
Add Sortable Directives2:24
which we'll address later on. But for now, let's install it using the CDN here. So we'll copy this. And let's go back to our Blade view. And I do have a stack for our scripts. So let's add that down here. So we can say push to our scripts. And it's based in the CDN link here. Okay, save that. And that's all we need for installation. Let's go back here. And for usage, it's pretty straightforward. So we can say wire:sortable. And this updateTaskOrder is what will be called on the Livewire class when we drag and then release the thing that we dragged. So this goes on the parent element right before we loop over all of our items here. So in our case, we have a body, let's go back to our Livewire component. So DragDropSongs. So right before our foreach is our body. So we'll put it here. Okay, let's update the method and say updateSongOrder. Sorry, typo. And we also need to specify an item and also a wire:key on the element that's repeating. So in
body. So we'll put it here. Okay, let's update the method and say updateSongOrder. Sorry, typo. And we also need to specify an item and also a wire:key on the element that's repeating. So in this case, it's going to be our table row. So right here, let's paste that in as changes to a song. So song. And we can also specify a wire:sortable.handle. So this allows us to specify what's draggable. So for now, we'll just put it in the TR as well. And then later on, we'll put it on a dedicated column. So let's put that here. Okay, save that. And if I did everything correctly, we should be able to drag our elements around. So let's go back to our app here. Let's try dragging one of these to the top. Actually, we have to refresh. So let me hard refresh. Let's try dragging this to the top. And it does somewhat work. And as I let go here, you'll see it tries to call that method. There we go. It says unable to call updateSongOrder method. So let's go ahead and
Implement Order Update Method4:10
this to the top. And it does somewhat work. And as I let go here, you'll see it tries to call that method. There we go. It says unable to call updateSongOrder method. So let's go ahead and define that method on our Livewire class. So DragDropSongs, make a new method here, or above here, actually. Let's say, updateSongOrder. And it takes a new param of the new order of items. So say newOrder. And let's just dd that to see what we get. So dd(newOrder). Okay, let's try that out. Go back here. Let's hard refresh. And I'm going to grab Thriller and move it above Bohemian Rhapsody. So the IDs should be one and three. So let's do that. Let's put this up here. And you can see we get this array. So the value is the ID of the thing I just dragged. And the order is just going to be the new order. So it's gonna be 123456. And there should be three. And it is cool. And the rest should be the same. So what we have to do
I just dragged. And the order is just going to be the new order. So it's gonna be 123456. And there should be three. And it is cool. And the rest should be the same. So what we have to do here is loop through all of these items and update the order of the IDs here. So pretty straightforward. Go ahead and do that. So let's get rid of this line. That's for foreach. We'll loop over our new orders. Let's say as item. And we don't need the value here. And for each iteration, let's grab the song and update the order. So we can say Song::find and the ID is going to be item value. Okay, so now we should have the song and we just have to update the new order. So we can say update and the order comes from item order. So order is item order. Okay. So now if I did that, right, the order should be updated in the database as we drag and drop. So let's save this. Let's try that again. That's hard refresh. Again,
Okay. So now if I did that, right, the order should be updated in the database as we drag and drop. So let's save this. Let's try that again. That's hard refresh. Again, I'm going to move further on top. And let's see if the database updates. So I'll let go. It's on top now. And let's see if we get the same order here. So 132654 in our database, after we refresh. So I'm going to refresh the database here. And we do get the proper order. So 132654. Let me just double check and rearrange everything here. Let me move this on top. Let's move this move M&M here. And let's move Jude down here. So now the order should be 463152. Let's double check. And it is. So everything is working. Now we do have a few options here to make this a better experience. So for example, as we're dragging, we can change the color of the thing we're dragging. So for example, if I drag this, we can change this to a different color,
make this a better experience. So for example, as we're dragging, we can change the color of the thing we're dragging. So for example, if I drag this, we can change this to a different color, or maybe add some sort of drop shadow. And if you look at the thing I currently grabbed, you'll see that the width changed. And we'll see how to fix that in a second. But for now, let's see if we can change the background color. So if we go back to the docs, you'll see this section here of classes we can make use of depending on the state of the thing we dragged. So down here, we can make use of the draggable mirror class. And then we can add any styles to it. So let's go ahead and do that. So let's go back to our blade file. And I do have a stack for our CSS as well. So I'll put that up here. Let's say push to our styles. We'll add one for our class in a style block. So it was draggable mirror, the class. And let's just say background
see if the width bug is fixed. So let's hard refresh this. Let's grab this song. And you can see it is the same width as the row in the table. Cool. So let's take a look at the options in sortable. So let's look for that class we can use. Right here, there's a link to the options for sortable. And the class name is now sortable drag. So let's grab this actually. And we'll replace what we have in our CSS. So instead of draggable mirror, it's now that new class, sortable drag. Let's get rid of this. Let's grab the background blue. And let's paste that in and see if it works. So back here, hard refresh, the background should now be blue. And it is cool. And just to make sure our drag and drop still works, it should now be 243615. Let's refresh this. And it still works. Cool. And just to make it look nicer, we'll update the styles here. I'll just say background white and give it a nice box shadow.
it should now be 243615. Let's refresh this. And it still works. Cool. And just to make it look nicer, we'll update the styles here. I'll just say background white and give it a nice box shadow. Now we also have an option to add an animation, which is pretty straightforward. If we look for animation here, you can see we can provide any option within the sortable package within wireSortable options. So let's grab this. And let's add that animation in. So this goes on the parent element. And let's add that animation in. And let's add that animation in. And let's add that let's add that animation in. So this goes on the parent element. So back to our Livewire component. Let's put it before the handle. And let's make it 500 milliseconds so we can see it. But realistically, I probably use 200 milliseconds or somewhere around there. Save this. Refresh. And that didn't work. Let's refresh again. Oh, sorry, that goes on the parent element.
Dispatch Success Feedback12:44
you can also provide some sort of feedback to the user to notify them that the operation was successful. So for that we can make use of browser events. So after we update the backend, we can dispatch an event and then listen for it in the front end. And in this case, we'll just alert. Let's grab this. Let's go back to our Livewire class. So dragDropSongs. So after this is done, the order should be complete. And we can dispatch this browser event. And how about we name this orderUpdated, we don't need to pass it any params. So let's get rid of this array here. And then we can listen for this in the front end. So let's grab that code. So we're just adding an event listener on the window. And then in this case, we'll just alert something. So let's put this in our dragDrop.blade.php underneath here in a script tag.
And then in this case, we'll just alert something. So let's put this in our drag drop .blade underneath here in a <script> tag. Space that in, let's save that. The name is orderUpdated. And how about we just say Order was updated, don't need this param. And we can just change the text here. Order was updated. So let's save that. And let's give that one more try to see if our events are being dispatched correctly. But back here, let's refresh. Let's move this song to the top, you have to drag it from here. And we do get that alert. Cool. And just to double check, make sure everything is still correct on the back end. So the order should be 431265. And it is. So yeah, if you need some sort of drag and drop functionality,
make sure everything is still correct on the back end. So the order should be 431265. And it is. So yeah, if you need some sort of drag and drop functionality, and also need to persist the order on the back end, definitely make use of this Livewire plugin. So as always, let's make a commit here. This is episode 10. Let's call it drag and drop with persistence.
