Sortable (https://github.com/RubaXa/Sortable) is a well-known library for drag and drop. Its simple yet powerful API makes its integration very easy.
Let's use it in our contact-management application to allow users to reorder the items for list-editor
elements using drag and drop.
First, we need to install the library by opening a console in the project directory and running the following command:
> npm install sortablejs --save
Next, we need to add it to the vendor bundle:
aurelia_project/aurelia.json
//Omitted snippet...
{
"name": "vendor-bundle.js",
"prepend": [
//Omitted snippet...
],
"dependencies": [
"sortablejs",
//Omitted snippet...
]
},
//Omitted snippet...
At this point, we can start using the library in our application.
Let's first add a handle to list items. This handle will be the area where the users will be able to drag items up and down the list. Additionally, we need to add a div
element, which will act as the container for the sortable items:
src/resources/elements/list-editor.html
<!-- Omitted snippet... --> <div ref="container"> <div class="form-group le-item ${animated ? 'au-animate' : ''}" repeat.for="item of items"> <template with.bind="item"> <div class="col-sm-1"> <i class="fa fa-bars fa-2x sort-handle pull-right"></i> </div> <template replaceable part="item"> <div class="col-sm-2"> <template replaceable part="label"></template> </div> <!-- Omitted snippet... --> </template> <!-- Omitted snippet... --> </template> </div> </div> <!-- Omitted snippet... -->
Here, we start by assigning a reference on the div
element containing the list items to the view-model's container
property. This container
will be required by the sortable
API to enable drag and drop on its children. Next, we remove the col-sm-offset-1
CSS class from the label column, and we add a sized-1 column, using Bootstrap's col-sm-1
CSS class containing a bars
Font Awesome icon and acting as a sort-handle
, using the CSS class of the same name.
Let's also add a CSS rule to change the drag handle's mouse cursor:
src/resources/elements/list-editor.css
/* Omitted snippet... */
list-editor .sort-handle {
cursor: move;
}
We can now use sortable
to add drag and drop support:
src/resources/elements/list-editor.js
//Omitted snippet... import sortable from 'sortablejs'; export class ListEditor { //Omitted snippet... moveItem(oldIndex, newIndex) { const item = this.items[oldIndex]; this.items.splice(oldIndex, 1); this.items.splice(newIndex, 0, item); } attached() { this.sortable = sortable.create(this.container, { sort: true, draggable: '.le-item', handle: '.sort-handle', animation: 150, onUpdate: (e) => { if (e.newIndex != e.oldIndex) { this.animated = false; this.moveItem(e.oldIndex, e.newIndex); setTimeout(() => { this.animated = true; }); } } }); setTimeout(() => { this.animated = true; }); } detached() { this.sortable.destroy(); this.sortable = null; } //Omitted snippet... }
Here, we start by importing the sortable
API. Then, when the element is attached to the DOM, we create a sortable
instance on the container
items that have the le-item
CSS class. We specify to sortable
that the item's child element that has the sort-handle
CSS class should be used as the drag handle. Finally, when an item is dropped at a different position in the list, the onUpdate
callback is triggered, in which we remove the dropped item from its previous position in the items
array and then insert it back at its new position.
We need to use splice
to remove then add the moved items, because Aurelia is unable to observe the array's index setter. It can only react to an array's changes by overriding the methods of Array.prototype
, such as splice
.
Additionally, we need to remove the animated
CSS class from the items before moving them, so the CSS rules triggering the animations won't be matched. We then add it back using setTimeout
, so it is only added once the templating engine is done removing the old view and adding the new one. This way, the animations that play when removing or adding items won't play when dragging and dropping items, which would look weird.
Finally, when the list-editor
is detached from the DOM, we call the destroy
method on the sortable
instance, in order to prevent memory leaks.
At this point, you can run the application, reorder the items for one of a contact's list properties, and save the form. In the details view, the items should appear in the new order in which you put them.
3.144.119.49