Skip to main content

Finally implemented jQuery .sortable() to enable drag-and-drop reordering on a skuid table. turned out to be much simpler than I expected! 

I have an Order__c field on the object which starts at index 1, and I’m just updating that field after every reorder.

Here’s my inline javascript:

(function(skuid){
var $ = skuid.$;
$(document.body).one(‘pageload’,function(){
var component = skuid.$C(‘MyComponentId’),
   listContents = component && component.element.find(‘.nx-list-contents’);
listContents.sortable({
   placeholder: “ui-state-highlight”,
   stop: function( event, ui ) {
       var data = ui.item.data(‘object’),
           model = data.list.model,
           movedRow = data.row,
           target = $(event.target);
       
       target.children().each(function(index,tr){
           var row =  $(tr).data(‘object’).row,
               order = row.Order__c;
          if (index + 1 !== order) {
              model.updateRow(row,‘Order__c’,index+1,{initiatorId:component._GUID});
          }
       });
           
   }
});
});
})(skuid);

Here’s the table in action:

How do you account for table pagination? For example, when showing rows 6-10 and reordering, it puts the sort order 1-5, ignoring the 1-5 that already exists on the table’s first page. Any workaround here or just advising users to ‘Show All’ before reordering?


Here’s the solution:

In the stopHelper function I found the current table page and page size to get my start number.


component = skuid.$C(tableId), currentPage = component.list.currentPage, currentPageSize = component.list.currentPageSize, startNumber = currentPage * currentPageSize;


Then, I add that startNumber to the updateRow function:


model.updateRow(row, orderByFieldApiName, index + 1 + startNumber, { initiatorId: component._GUID });

Nice work, Craig!


Thanks! Always nice to answer your own question. I did notice if you have display all rows set, you need to add some logic to account for the ‘All’ response from currentPageSize:


if (isNaN(startNumber)) startNumber = 0;<br>

Always love it when people are able to answer their own question and share their findings with the community. Thanks, Craig!


Hey everyone - This is fantastic!  I am s javascript rookie, so could use a little help.  I implemented this for a multi-tab table, and when dragging a line, my mouse arrow is a significant distance away from the actual row in motion.  Any suggestions on how to improve the “tightness” of the arrow to the moving row to improve user experience? Thanks!


Anne, could you post the code that you’re using? I believe there are a couple versions in this thread. I had a similar issue when I first implemented it and needed to adjust the helper styling with some CSS to bring it closer. 


I copied and pasted the exact version from Matt’s original post.  Another wrinkle - I just installed Millau (11.0.6) release and now I get an error:   There was a problem rendering a component of type skuidpage: Cannot read property ‘sortable’ of undefined


so painfully in the dark on this one but it is what i really want to implement.  Is there a walk thru on where/how implement?  Are you applying this snippet to a row action or what?


Thank you for this code! I discovered a bug in the implementation. On re-rendering the table the elements move out of order (say you add a new row to the table and the table re-renders to display the new row). To keep the elements in order on re-render, you actually need to sort the model.data array. I’ve added that sort with a line of code to the original example. Here’s the updated code:

var listContents = component && component.element.find(‘.nx-list-contents’); listContents.sortable({
placeholder: “ui-state-highlight”,
stop: function( event, ui ) {
var data = ui.item.data(‘object’),
model = data.list.model,
movedRow = data.row,
target = $(event.target);

target.children().each(function(index,tr){
var row = $(tr).data(‘object’).row,
order = row.Order__c;
if (index !== order) {
model.updateRow(row,‘Order__c’,index,{initiatorId:component._GUID});
}
});
//Make sure model data is properly sorted
model.data.sort((a, b) => (a.Order__c > b.Order__c) ? 1 : -1);
}
});```
Question: Has anyone tried getting drag-and-drop to work between models? For instance my use case would be I have a Queue and a Table and I’d like the user to be able to drag an item from the Queue into the table and it run javascript to create a new row with customized field values based on what was dragged at the appropriate index in the table’s model.


This has been working great. Thank you!

However on a v1 page, somehow lost the actual visible place holder. It moves the row but you can’t see what you are moving. Any ideas? What actually defines 'ui-state-highlight" Thanks in advance!

listContents.sortable({
placeholder: “ui-state-highlight”,
stop: function( event, ui ) {
var data = ui.item.data(‘object’),
model = data.list.model,
movedRow = data.row,
target = $(event.target);

target.children().each(function(index,tr){
var row = $(tr).data(‘object’).row,
order = row.LineItemListOrder__c;
if (index + 1 !== order) {
model.updateRow(row,‘LineItemListOrder__c’,index+1,{initiatorId:component._GUID});
}
});

}
});```