Thank you to David Konrad for his guidance from his answer on another question on how to add a row in the middle of a table.
The first thing I did is start by creating an Action
column in my table and dynamically add the Up
or Down
options.
{
name: 'action',
data: null,
title: 'Action',
searchable: false,
sortable: false,
render: function (data, type, full, meta) {
if (type === 'display') {
var $span = $('<span></span>');
if (meta.row > 0) {
$('<a class="dtMoveUp">Up</a>').appendTo($span);
}
$('<a class="dtMoveDown">Down</a>').appendTo($span);
return $span.html();
}
return data;
}
}
Then, I added code in the drawCallback
to remove the Down
arrow of the last row and bind the click event to moveUp
and moveDown
functions:
'drawCallback': function (settings) {
$('#ArgumentsTable tr:last .dtMoveDown').remove();
// Remove previous binding before adding it
$('.dtMoveUp').unbind('click');
$('.dtMoveDown').unbind('click');
// Bind click to function
$('.dtMoveUp').click(moveUp);
$('.dtMoveDown').click(moveDown);
}
Then I coded the move up/down functions. It is important to note that my data has a order
property that I use to change the order. This order
is displayed as the first column and makes it the default sort column:
// Move the row up
function moveUp() {
var tr = $(this).parents('tr');
moveRow(tr, 'up');
}
// Move the row down
function moveDown() {
var tr = $(this).parents('tr');
moveRow(tr, 'down');
}
// Move up or down (depending...)
function moveRow(row, direction) {
var index = table.row(row).index();
var order = -1;
if (direction === 'down') {
order = 1;
}
var data1 = table.row(index).data();
data1.order += order;
var data2 = table.row(index + order).data();
data2.order += -order;
table.row(index).data(data2);
table.row(index + order).data(data1);
table.page(0).draw(false);
}
Note: It is important to understand that when you ask DataTable to draw()
your table again, it will use your data to sort the results according to the parameters set in the DataTable definition. This is why I chose, for this example, to set the order
as the first column (default sort) and alter my data objects directly (instead of playing with internal information from DataTable). That makes things a lot easier.
Note 2: It is really important that your data is received by the DataTable already sorted by order
. Otherwise, this solution won't work as is.
You can check a full working example here:
https://jsfiddle.net/kxfx489y/4/