Reputation: 944
I'm trying to implement the sortable-list feature form jquery-ui with aurelia. Whats the best way to update the items (inside aurelia controller) with the new order from the dom? Is "ref" an approach here? Easy re-sort the list-items in the dom, but how apply the changes to the aurelia-list-object?
<ul class="sortable">
<li repeat.for="item of items">
Stuff.
</li>
</ul>
One Approach would be to attach the $index to the li-item, read them with jquery after the order was changed and create an new array with the order ([0,3,1,2]). Then iterate throigh this array and push the items of the original "item"-array in the controller to a new array according to their index. This seems rather clunky and unperformant though.
Is there a more elegant solution?
Upvotes: 0
Views: 296
Reputation: 91
We found that Aurelia doesn't really take kindly to "others" rearranging the DOM under its nose. The specific case that was broken for us (from memory) was when you drag the item around and return it to its original position.
What we did was attach an event handler for "sortstop" to the sortable component, and the event handler did this (this is Typescript) -- items is our list of items we have bound to, and refSortable is the sortable element:
onStop( event: JQueryEventObject, ui: any ): boolean
{
let endPos = ui.item.index( );
let startPos = ui.item.data( "start_pos" );
$( this.refSortable ).sortable( "cancel" );
let movedItem = this.items[ startPos ];
if( startPos === endPos )
{
// KLUDGE: even though the item has not moved, we need to create a new one to force Aurelia to rebind
let newItem = new ExportListItem( movedItem.id, movedItem.caption, movedItem.sourceObject );
movedItem = newItem;
}
this.items.splice( startPos, 1 );
this.items.splice( endPos, 0, movedItem );
// We end up with a duplicate DOM element that needs to be removed.
ui.item.remove( );
}
I won't say it's elegant by any stretch, but it gets Aurelia behaving correctly.
Upvotes: 1