Move row in dataTable one position up

Move row in dataTable one position up

Denis.David@dqs.deDenis.David@dqs.de Posts: 28Questions: 8Answers: 1
edited September 2015 in DataTables

Dear all,

I created a function (mapped to button "up") which moves a selected row in a dataTable one position up by exchanging the "orderid" column value (first column) of the row to move and the row above it.

The problem is that the change of both column values is reflected correctly in edit mode (clicking the cell in inline-edit mode reveals the changed value) but in view mode the old value for the lower row is still shown. The value change of the upper row is shown correctly both in view and edit mode.

Have I missed something?

Of course, if this will work I would like to have the same function for moving a row one position down.

Thanks for your help!

Here is my code:

var t = $('#' + tblName).DataTable({
        "ordering" : false,
        "scrollCollapse": true,
        "paging": false,
        "searching": false,
        "info": false,
        "rowId": tblKey,
        columns: fields,
        data: [],
        dom: "Bfrtip",
        'aaSortingFixed': [
            [0, 'asc']
        ],
        bServerSide: false,
        select: true,
        "createdRow": function(row, data, index) {
            $('#' + tblName).dataTable().fnUpdate(index + 1, row, 0, true);
        },
        buttons: [{
            extend: 'selectedSingle',
            sButtonClass: "dataTableButton",
            text: 'Up',
            action: function(e, dt, node, config) {
                var selected = dt.row({
                    selected: true
                });
                var selectedData = selected.data();
                var selectedOrderId = selectedData.OrderId;
                
                
                var orderid = dt.row({
                    selected: true
                }).data().OrderId;
                
                var key = dt.row({
                    selected: true
                }).data()[tblKey];
                
                $('#' + tblName).dataTable().fnUpdate(orderid, $('tr#' + key).prev('tr'), 0, false);
                $('#' + tblName).dataTable().fnUpdate(orderid -1, $('tr#' + key), 0, true);
            }
        }]
}

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 54,688Questions: 1Answers: 8,553 Site admin

    I don't immediately see anything wrong with the above code. Can you link to the page so it can be debugged please?

    I would suggest using the new API (cell().data() rather than the legacy API ( fnUpdate ), but that shouldn't make much difference really.

    Allan

  • Denis.David@dqs.deDenis.David@dqs.de Posts: 28Questions: 8Answers: 1

    Dear Allan,

    Thanks for the quick reply.
    Unfortunately I cannot share the project as it resides on an internal network.

    But during deeper research I could figure out the point where the problem arises.

    Stepping through the two fnUpdate lines shows the updated values correctly directly afterwards. Btw, cell().data() behaves exactly the same.

    BUT when stepping further through the debugger, in the jquery-2.1.1.js library after executing the line return typeof jQuery !== strundefined ... at the very bottom of the following code part, the selected line again shows the pre-updated value (the row above is correctly updated). When selecting this record again, opening the edit form with the edit button and clicking the "update" button (without manually changing the value again, in the edit form it shows correctly updated!), the updated value is shown correctly in the datatable.

    Any thoughts?

    jQuery.event = {
    
        global: {},
    
        add: function( elem, types, handler, data, selector ) {
    
            var handleObjIn, eventHandle, tmp,
                events, t, handleObj,
                special, handlers, type, namespaces, origType,
                elemData = data_priv.get( elem );
    
            // Don't attach events to noData or text/comment nodes (but allow plain objects)
            if ( !elemData ) {
                return;
            }
    
            // Caller can pass in an object of custom data in lieu of the handler
            if ( handler.handler ) {
                handleObjIn = handler;
                handler = handleObjIn.handler;
                selector = handleObjIn.selector;
            }
    
            // Make sure that the handler has a unique ID, used to find/remove it later
            if ( !handler.guid ) {
                handler.guid = jQuery.guid++;
            }
    
            // Init the element's event structure and main handler, if this is the first
            if ( !(events = elemData.events) ) {
                events = elemData.events = {};
            }
            if ( !(eventHandle = elemData.handle) ) {
                eventHandle = elemData.handle = function( e ) {
                    // Discard the second event of a jQuery.event.trigger() and
                    // when an event is called after a page has unloaded
                    return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
                        jQuery.event.dispatch.apply( elem, arguments ) : undefined;
                };
            }`
    
  • allanallan Posts: 54,688Questions: 1Answers: 8,553 Site admin
    Answer ✓

    Hi,

    I'm afraid I'm really not sure what would cause what you are seeing. I would need a test case to be able to debug the issue to discover what is happening. Unfortunately I don't recall anyone else noting a similar issue (which isn't to say that there might not be a bug, just that I don't remember it being raised before) so I don't really have much to go on.

    Allan

  • Denis.David@dqs.deDenis.David@dqs.de Posts: 28Questions: 8Answers: 1

    Dear Allan,

    Finally figured it out.

    It is necessary to first do a editor.blur() and then call the fnUpdate lines. Obviously leaving the edit mode active is preventing the data update to be reflected in dataTable view mode.

    Maybe this helps someone else running into this issue.

    Thanks anyway for your efforts to help.

    Best regards,

    Denis

  • Denis.David@dqs.deDenis.David@dqs.de Posts: 28Questions: 8Answers: 1

    Just for the ones interested in the complete move row up/down functionality, here is the optimized and working code snippet:

    buttons: [{
                extend: 'selectedSingle',
                sButtonClass: "dataTableButton",
                text: 'Up',
                action: function(e, dt, node, config) {
                    dataTableEditorArray[tblName].blur();
    
                    var currentRow = dt.row({
                        selected: true
                    });
    
                    var currentRowIndex = currentRow.index();
                                   
                    if (currentRowIndex < 1) {
                        return;
                    }
    
                    var currentRowData = currentRow.data();
                    var prevRow = dt.row(currentRowIndex-1);
                    var prevRowData = prevRow.data();
    
                    currentRow.data(prevRowData);
                    prevRow.data(currentRowData).draw();
                }
            }, {
                extend: 'selectedSingle',
                sButtonClass: "dataTableButton",
                text: 'Down',
                action: function(e, dt, node, config) {
                    dataTableEditorArray[tblName].blur();
                    var rowCount = $('#' + tblName).dataTable().fnGetData().length;
    
                    var currentRow = dt.row({
                        selected: true
                    });
    
                    var currentRowIndex = currentRow.index();
                                   
                    if (currentRowIndex+1 == rowCount) {
                        return;
                    }
    
                    var currentRowData = currentRow.data();
                    var nextRow = dt.row(currentRowIndex+1);
                    var nextRowData = nextRow.data();
    
                    currentRow.data(nextRowData);
                    nextRow.data(currentRowData).draw();
                    
                }
            }, {
    
  • allanallan Posts: 54,688Questions: 1Answers: 8,553 Site admin

    Excellent - thanks for posting back with your solution!

    Regards,
    Allan

  • Denis.David@dqs.deDenis.David@dqs.de Posts: 28Questions: 8Answers: 1
    edited October 2015

    Just wanted to share an improved/corrected version of the up/down button functionality. As index() is not updating after exchanging rows (I initially understood it is the (visual) row number but obviously it is the internal row index in the table store and does not change after table initialization). So the first version above does not work correctly with subsequent row moves.

    Here is the revised version, The row selection sticks with the selected row before hitting up/down so you can subsequently push the up button to get the row pushed up through the whole table or vice versa with the down button. Enjoy!

            buttons: [{
                extend: 'selectedSingle',
                sButtonClass: "dataTableButton",
                text: 'Up',
                action: function(e, dt, node, config) {
                    dataTableEditorArray[tblName].blur();
                    
                    var currentRow = dt.row({
                        selected: true
                    });
                    
                    var currentRowData = currentRow.data();
                    
                    var currentRowDataOrderId = currentRow.data().OrderId;
                    
                    if (currentRowDataOrderId < 2) {
                        return;
                    }
    
                    var prevRow;
                    dt.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
                        var data = this.data();
                        if (data.OrderId == currentRowDataOrderId -1) {
                            prevRow = this;
                        }
                    });
                    
                    var prevRowData = prevRow.data();
                    var prevRowDataOrderId = prevRowData.OrderId;
                    
                    dt.cell(currentRow, 0).data(prevRowDataOrderId);
                    dt.cell(prevRow, 0).data(currentRowDataOrderId);
                    
                    $('#' + tblName).DataTable().draw();
                }
            }, {
                extend: 'selectedSingle',
                sButtonClass: "dataTableButton",
                text: 'Down',
                action: function(e, dt, node, config) {
                    dataTableEditorArray[tblName].blur();
                    var rowCount = $('#' + tblName).dataTable().fnGetData().length;
                    
                    var currentRow = dt.row({
                        selected: true
                    });
                    
                    var currentRowData = currentRow.data();
                    
                    var currentRowDataOrderId = currentRow.data().OrderId;
                    
                    if (currentRowDataOrderId == rowCount) {
                        return;
                    }
    
                    var nextRow;
                    dt.rows().every( function ( rowIdx, tableLoop, rowLoop ) {
                        var data = this.data();
                        if (data.OrderId == currentRowDataOrderId +1) {
                            nextRow = this;
                        }
                    });
                    
                    var nextRowData = nextRow.data();
                    var nextRowDataOrderId = nextRowData.OrderId;
                    
                    dt.cell(currentRow, 0).data(nextRowDataOrderId);
                    dt.cell(nextRow, 0).data(currentRowDataOrderId);
                    
                    $('#' + tblName).DataTable().draw();
                }
            }]
    
This discussion has been closed.