Make Table Rows Sortable Using jQuery UI Sortable
by Brian Grinstead
So you want to make table rows sortable using jQuery UI? Luckily, the Sortable interaction does most of the work for you.
But there’s a catch: one problem that I ran into when implementing this (with UI version 1.7) was the cell widths of the row would collapse once I started dragging it.
Suppose you have a table of data, like this one:
<table id="sort" class="grid" title="Kurt Vonnegut novels"> <thead> <tr><th>Year</th><th>Title</th><th>Grade</th></tr> </thead> <tbody> <tr><td>1969</td><td>Slaughterhouse-Five</td><td>A+</td></tr> <tr><td>1952</td><td>Player Piano</td><td>B</td></tr> <tr><td>1963</td><td>Cat's Cradle</td><td>A+</td></tr> <tr><td>1973</td><td>Breakfast of Champions</td><td>C</td></tr> <tr><td>1965</td><td>God Bless You, Mr. Rosewater</td><td>A</td></tr> </tbody> </table>
Your first attempt to make it sortable might look like this:
$("#sort tbody").sortable().disableSelection();
And it actually works, but there is a bit of a problem. The cell widths seem to be collapsing once you start dragging a row (notice how close the “C” cell is to the “Breakfast of Champions” cell). It looks like this:

The problem has to do with the helper object. The helper object is basically the DOM element that follows the cursor during the drag event. When it is created by default, the cells collapse to the size of the content inside of them.
You can specify a function that returns a jQuery object to create a custom helper object. By creating a function that will keep the cell widths consistent, this problem can be fixed.
// Return a helper with preserved width of cells
var fixHelper = function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
};
$("#sort tbody").sortable({
helper: fixHelper
}).disableSelection();
Now it works as expected:

Tags: HTML, Javascript, cell, cross-browser, jQuery, jQuery-UI, sortable, table, td, width
« Keep Original Variable State Between Event Binding and Execution – JavaScript jQuery Custom Selector for selecting elements by exact text :textEquals »
July 30th, 2009 at 8:17 pm
[...] wrote an article over on the LANIT Development blog about a problem that I ran into when trying to set up a basic [...]
September 10th, 2009 at 3:16 pm
good job,
but i”ve a question, how do you implement the placeholder?
November 13th, 2009 at 4:56 pm
This was incredibly useful! Thanks for figuring this out.
November 21st, 2009 at 12:15 am
How does this code actually work?
$(this).width($(this).width());
How does setting the width back to itself do anything at all?
December 17th, 2009 at 6:02 am
veeeeeeeeeeeery nice… tks
December 30th, 2009 at 11:53 am
There is a problem when formating table using css with border-collapse: collapse. It doubles the border on sort. Do you know jow to fix this?
January 7th, 2010 at 11:55 pm
Note that there is a ”forceHelperSize” now.
January 8th, 2010 at 12:11 am
width( ) returns the calculated width in pixels. By setting width with this calculated width, you are explicitly stating its width.
January 8th, 2010 at 12:11 am
Which on closer inspection, doesn”t help
January 10th, 2010 at 4:55 pm
I can”t seem to get this to work? my html is as follows:
PositionCarDriverFastest Lap
1Lamborghini Gallardo SWills1:38.277
2Lamborghini MurcielagoNick1:38.392
3Audi R8 V10Aidy1:37.938
4Porche 911 GT2Phil1:38.000
5Ford GTMatt1:36.814
and in my jQuery script I have:
$(document).ready(function() {
$(”.sortable”).sortable({
helper: fixHelper,
cursor: ”move”,
placeholder: ”ui-state-highlight”,
axis: ”y”,
update: function(e, ui) {
$el = $(ui.item);
$el.effect(“highlight”,{},2000);
$(“.sortable tr”).each(
function(currentIndex) {
$(this).find(“td:first”).text(this.rowIndex);
});
href = ”/myReorderFunctionURL/”;
$(this).sortable(“refresh”);
sorted = $(this).sortable(“serialize”, ”id”);
$.ajax({
type: ”POST”,
url: href,
data: sorted,
success: function(msg) {
//do something with the sorted data
}
});
}
}).disableSelection();
// Return a helper which preserves the width of the table cells
var fixHelper = function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
};
});
I tried removing most of the jQuery and just keeping the minimal required but still my table rows cells collapse
.
Any ideas?
January 10th, 2010 at 4:57 pm
It would appear I fail at posting HTML
My HTML is here: http://pastebin.com/m211d85d6
January 10th, 2010 at 5:08 pm
Never mind, I found the answer here: http://stackoverflow.com/questions/1307705/jquery-ui-sortable-with-table-and-tr-width
Works Perfectly!
Thanks to both Brian Grinstead and Dave Miller for this awesome solution
January 12th, 2010 at 6:34 pm
Glad it worked! I will make a note of his method of cloning the row to prevent having explicit widths set on the original row.
May 5th, 2010 at 2:36 pm
Hello,
How we can get the serialized values in this case?
thanks
July 12th, 2010 at 12:00 pm
Very nice saved me a lot of time
August 4th, 2010 at 10:54 pm
oh man, this saved me a hell of a lot of time, thanks for doing this! good work
August 6th, 2010 at 11:52 am
Thanks for posting this. Was starting to loose time on this one.
August 9th, 2010 at 11:37 am
I was doing R&D for the same thing and was not getting success. Your code works and it saved my time. Many many thanks to you.
August 11th, 2010 at 3:12 am
Thanks much, this saved me from having to dig into the root of this problem. Much appreciated!!!
September 3rd, 2010 at 6:27 pm
Ive found that this isn”t usually necessary if you use sortable like this:
$(“.sortable tbody”).sortable({
items: “tr”
});
October 19th, 2010 at 5:30 pm
@dharh that doesn”t work, still messes up the data inside the tr.
@Brian using your fixHelper function hides the element I want to drag… I have the trs inside a tbody and it”s the tbody that I make sortable.
October 19th, 2010 at 5:33 pm
Yet, the answer below works better as @Wills suggested.
http://stackoverflow.com/questions/1307705/jquery-ui-sortable-with-table-and-tr-width
November 8th, 2010 at 4:25 pm
Great job, thanks for posting!
November 8th, 2010 at 5:31 pm
Fantastic, just what I was looking for!
November 14th, 2010 at 12:40 am
What data do you send to update?
How does this code work?
$(this).sortable(“serialize”, ‘id’);
I try to get any data for the sorted and I can not get any..
November 15th, 2010 at 7:10 pm
Amir,
Here is documentation for the serialize method: http://jqueryui.com/demos/sortable/#method-serialize
I believe that by default, serialize will use the “id” attribute for each item with the output. The second parameter can change which attribute it looks at, but I think in the latest version, the second parameter needs to be an object hash, like { key: ”id” }.
January 30th, 2011 at 10:51 am
hi,
can you provide an example page for this.
thanks,
Vikky
January 31st, 2011 at 4:58 pm
Vikky, I made an http://jsbin.com/ehodo4'‘ rel=”nofollow”>example of jQuery table row sorting for you to help show what is going on and how to fix it. If you click the “Edit with JSBin” link in the top right corner of the page, you can make changes to the page.
March 29th, 2011 at 9:57 am
Many thanks, I found this example to be better than the one that clones the elements which led to unexpected side effects
November 8th, 2011 at 7:18 pm
yeahhhh!!!!!! thank””s a lot!!!!!!!!!!!!!!
February 10th, 2012 at 2:49 am
Kompass…
[...]Foliotek Development Blog » Blog Archive » Make Table Rows Sortable Using jQuery UI Sortable[...]…
March 1st, 2012 at 10:58 pm
Awesome! This turned a problem that would have taken hours to solve into a completely trivial task. Thank you very much!
April 11th, 2012 at 2:51 am
Good post, helped me for my need. Showing data in tables that needs sorting. This fixed that nasty collapse issue with no effort. Thanks for supporting the community.
April 26th, 2012 at 9:11 am
Thanks man!
May 21st, 2012 at 7:36 am
Incredibly useful and easy to implement. Thanks.
June 5th, 2012 at 5:05 am
I”m noticing a problem on my own implementation, and I can reproduce it on the jsFiddle, which is that there is a spacing issue (a separation between two rows) when I repeatedly drag the “2nd to last row” to be the last row. To really see the separation, do that like 20 times or so. This shows up the most in the “Modified fix”, and only a small gap appears in the “original fix”. Worst thing is, I don”t know what the space is; it looks like padding or margin on one of the rows, but using Firebug there”s no such space at all.
July 10th, 2012 at 1:14 pm
Works well – thanks.
But if I limit the axis to “y” safari (OSX, latest regular Version) produces odd errors.
With the first and last it always works, but any in between places the helper object outside the right table-border. It seems that Safari is somehow changing the table-width when you add the placeholder. The error is pretty random.
If you insert the option ” axis: ”y” ” into your example you can see the error in safari too.
Any idea how to fix this or what the cause of this is?
August 23rd, 2012 at 10:54 am
How do you deal with two of this sortable tables that are connected to each other with ”connectWith”. This issue starts with one of the table starts as being empty. Some of the solutions starts with forcing a min-size on the tbody (Not working) or having the sortable selector by ”mytable” rather than ”mytable tbody” and then the items selector being ”tbody >tr”. That seems to have problems with dragging items back and forth between the two tables. Has anyone implemented it successfully?
August 23rd, 2012 at 12:37 pm
gkohen,
Can you set up a jsbin example with this situation?
September 26th, 2012 at 2:35 pm
Thank you so much! This will help me a lot
Thanks from Brazil
October 27th, 2012 at 11:24 am
Great stuff man! I don”t know how u came up with “$(this).width($(this).width())” – but it works! Cheers!
October 30th, 2012 at 8:18 am
works perfectly fine. Thanks a lot
December 6th, 2012 at 9:18 pm
If you have a checked radio button inside your table cells that you are sorting, the ”fixHelperModified” function will cause the radio button to be unchecked. The ”fixHelper” function does not cause this behavior.
December 22nd, 2012 at 11:36 pm
It does work perfectly. Thanks
February 12th, 2013 at 7:44 am
Good work! I love this script.
March 19th, 2013 at 11:25 pm
[...] Which I found on here http://www.foliotek.com/devblog/make-table-rows-sortable-using-jquery-ui-sortable/ [...]
March 22nd, 2013 at 2:50 am
Works perfectly for me, thanks.
But on question.. why it didm”t work when i”m using containment the restrict the movement area?
May 20th, 2013 at 12:08 pm
Works perfectly. Very Nice job. Thanks lot…