Sort Table with Drag and Drop

Matt SonesMatt Sones 💎💎💎
edited June 29, 2020 in Ideas
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:



12
12 votes

Awaiting Review · Last Updated

«1

Comments

  • Pat VachonPat Vachon 💎💎💎
    edited June 25, 2020
    Very slick. Going to use this for sure!
  • edited March 2, 2017
    The one problem with this solution is that it makes tables with textareas in them uneditable or selectable.
  • Matt SonesMatt Sones 💎💎💎
    edited December 7, 2016
    Hmm, even if you click on the 'edit' row action?
  • edited August 31, 2016
    Yes, it blocks the rich text panel that comes up.
  • edited October 15, 2019
    I love this and can work around the inline editing of the text. Thanks!
  • Karen WaldschmittKaren Waldschmitt 🛠️ 
    edited March 2, 2017
    Matt~

    This is very cool!

    Thanks for sharing with the community :)
    Karen
  • edited August 31, 2016
    Karen, can you file the rich text issue as a bug with skuid?
  • Pat VachonPat Vachon 💎💎💎
    edited June 25, 2020
    Works great. I additional save the model after setting the index.
    // Sprint Work Drag & Drop reorder      var component = skuid.$C('sk-39dlIj-483'),          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.Sprint_Rank__c;                  if (index + 1 !== order) {                      model.updateRow(row,'Sprint_Rank__c',index+1,{initiatorId:component._GUID});                  }                });                  $.blockUI();                  $.when( model.save() )                      .done(function(){                          $.unblockUI();                      });                     }      });
  • Karen WaldschmittKaren Waldschmitt 🛠️ 
    edited December 21, 2016
    John~

    Clarification question: Is this specific to when you use Matt's snippet or to tables in general? 

    Thanks!
    Karen
  • edited August 31, 2016
    This is anytime you apply a JQuery UI sortable to a skuid table.
  • Amy DewaalAmy Dewaal ✭✭
    edited May 23, 2018
    John,

    Have you tried tabbing over to the rich text area? 

    Thanks!
    Amy
  • edited August 31, 2016
    You can tab over but you can't click into it. It's not really an acceptable solution to train users to do this.
  • edited June 19, 2017
    I found a workaround for the rich text issue: use a handle for the sortable action. Add a row action with no actions and put in the class of the icon. Here is code with the handle, save and requery: (function(skuid){ var $ = skuid.$; $(document.body).one('pageload',function(){ var component = skuid.$C('johntt'), listContents = component && component.element.find('.nx-list-contents'); listContents.sortable({ placeholder: "ui-state-highlight", handle: '.fa-ellipsis-v', 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}); } }); $.blockUI(); $.when(model.save()).done(function(){ model.updateData(function(){ $.unblockUI(); }); }); } }); }); })(skuid);
  • edited August 9, 2016
    Clever workaround! I like it
  • Amy DewaalAmy Dewaal ✭✭
    edited May 23, 2018
    John,

    I'm glad you found a workaround, and thanks for sharing it with the community!

    Thanks!
    Amy
  • Matt SonesMatt Sones 💎💎💎
    edited December 7, 2016
    Perfect! I'm definitely implementing the handle. Thanks, John!
  • edited August 9, 2016
    I took this and made a super fancy version :D
  • edited August 31, 2016
    Going further down the fancy rabbit hole I used this http://tobiasahlin.com/spinkit/ to put in a css based spinner
  • SriSri
    edited August 10, 2016
    Matt, this is cool. Will come in very handy
  • edited August 10, 2016
    I remodeled my super fancy version above as a master page snippet invokable from child pages  :D
  • edited January 27, 2017
    This is a dumb question, but how do I do this part:

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


  • edited August 31, 2016
    Add a field called Order to the object and model or rename the field in the javascript to another field you already defined to do this.
  • SegSeg ✭✭
    edited August 31, 2016
    This is an extremely dumb question.... i've put the first presented code as a new in-line snippet, and modified the component Id and the field name...is there anything else I need to do to make it work? 
  • edited September 1, 2016
    It's not a snippet it's an inline code (the option without parenthesis).
  • SegSeg ✭✭
    edited October 12, 2016
    Thanks John! however when i move them the values of the index field remain the same. is it supposed to do that?
  • Craig RosenbaumCraig Rosenbaum ✭✭✭✭
    edited September 12, 2019
    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?
  • Craig RosenbaumCraig Rosenbaum ✭✭✭✭
    edited July 25, 2017
    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       });
  • Matt SonesMatt Sones 💎💎💎
    edited July 25, 2017
    Nice work, Craig!
  • Craig RosenbaumCraig Rosenbaum ✭✭✭✭
    edited July 25, 2017
    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;
  • Karen WaldschmittKaren Waldschmitt 🛠️ 
    edited July 25, 2017
    Always love it when people are able to answer their own question and share their findings with the community. Thanks, Craig!
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!