Dragging and dropping with sortable

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.

Installing the library

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.

Adding drag and drop to list-editor

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.119.49