4

I am using DataTables along with the rowReorder plugin against a static table (non AJAX) - everything initialises fine but when I drag a row, whilst it moves within the table, when I drop it goes back to its original location without refreshing (i.e. it never actually moves location - am aware I will need to update via AJAX to get the move permanent but I need this to work first!)

I added this code to try and tell me what was happening:

    table.on('row-reorder', function (e, diff, edit) {
        var result = 'Reorder started on row: '+edit.triggerRow.data()[1]+'<br>';

        for (var i=0, ien=diff.length ; i<ien ; i++) {
            var rowData = table.row( diff[i].node ).data();

            result += rowData[1]+' updated to be in position '+
                diff[i].newData+' (was '+diff[i].oldData+')<br>';
        }

        $('#event-result').html('Event result:<br>'+result);
    }); 

and when I use this, in event-result, I get something like:

Event result:
Reorder started on row: 3
4 updated to be in position (was )
5 updated to be in position (was )
3 updated to be in position (was )

The plugin can see that I am trying to move row 3 but it doesn't seem to be able to determine where I am trying to drop it hence the new and old position are blank whereas on https://datatables.net/extensions/rowreorder/examples/initialisation/events.html you can see that it should "know" the location to drop and where to re order the 2 adjoining columns to.

In all the examples I have seen there are no id's added to the rows etc so I assuming this is being caused by a plugin clashing - anyone seen this before and know how to fix?

Here is my whole Datatables code:

    $.extend( $.fn.dataTable.defaults, {
        autoWidth: false,
        dom: '<"datatable-header"fBl><"datatable-scroll-wrap"t><"datatable-footer"ip>',
        language: {
            search: '<span></span> _INPUT_',
            lengthMenu: '<span></span> _MENU_',
            paginate: { 'first': 'First', 'last': 'Last', 'next': '&rarr;', 'previous': '&larr;' }
        }
    });                     
   // Column selectors
    var table = $('.datatable-button-html5-columns').DataTable({
        //dom: 'lBfrtip',
        initComplete: function () {
            this.api().columns('.select-filter').every( function () {
                var column = this;
                var select = $('<select class="form-control"><option value=""></option></select>')
                    .appendTo( $(column.footer()).empty() )
                    .on( 'change', function () {
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );

                        column
                            .search( val ? '^'+val+'$' : '', true, false )
                            .draw();
                    } );

                column.data().unique().sort().each( function ( d, j ) {
                    select.append( '<option value="'+d+'">'+d+'</option>' )
                } );
            } );
        },
        colReorder: true,
        orderCellsTop: true,
        stateSave: true,
        pageLength: 10,
        order:[[ 1, "asc" ]],
        language: {
            url: "/assets/js/plugins/tables/datatables/lang/en.php"
        },          
        select: true,
        rowReorder: {
            selector: 'tr',
            update: true
        },          
        buttons: {            
            dom: {
                button: {
                    className: 'btn btn-default'
                }
            },
            buttons: [
                {
                    extend: 'colvis',
                    titleAttr: 'Columns'
                },
                {
                    extend: 'copyHtml5',
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    extend: 'excelHtml5',
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    extend: 'pdfHtml5',
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    extend: 'print',
                    exportOptions: {
                        columns: ':visible'
                    }
                },
                {
                    text:      '<span id="resetTable">Reset</span>'
                }                   

            ]
        },
        responsive: {
            details: {
                type: 'column',
                target: 'tr'
            }
        },
        columnDefs: [
            {
                className: 'control',
                orderable: true,
                targets:   0
            }
        ]                           
    });

            // Setup event
    table.on('row-reorder', function (e, diff, edit) {
        var result = 'Reorder started on row: '+edit.triggerRow.data()[1]+'<br>';

        for (var i=0, ien=diff.length ; i<ien ; i++) {
            var rowData = table.row( diff[i].node ).data();

            result += rowData[1]+' updated to be in position '+
                diff[i].newData+' (was '+diff[i].oldData+')<br>';
        }

        $('#event-result').html('Event result:<br>'+result);
    });

4 Answers 4

4

In datatable initialization code, remove order attribute. If we use order then drag and drop will not work.

Example with order - not working

table = $('#ConfigMenuTable').DataTable({
  data: testData,
  "rowReorder":  {
                selector: 'td:nth-child(1)'
            },            
  "order":[[ 1, "asc" ]],
  "columns": [
                {"visible": false},                         
                {"width": "20%", "className": 'reorder'},                       
                {"visible": false,"searchable": true, "width": "15%"},     
                {"orderable": false, "searchable": false},  
                {"orderable": false, "searchable": false},
                {"orderable": true, "searchable": false}                
            ]

});

Example without order - working

table = $('#ConfigMenuTable').DataTable({
  data: testData,
  "rowReorder":  {
                selector: 'td:nth-child(1)'
            }, 
  "columns": [
                {"visible": false},     
                {"width": "20%", "className": 'reorder'},   
                {"visible": false,"searchable": true, "width": "15%"},  
                {"orderable": false, "searchable": false},
                {"orderable": false, "searchable": false},
                {"orderable": true, "searchable": false}                
            ]    
});
Sign up to request clarification or add additional context in comments.

Comments

3

Try adding an ID or sequence to the table. In the basic initialization example, it says:

The first column in the table is a sequence number that provides the basis for the ordering.

In that example it has a hidden sequence column:

columnDefs: [
    { targets: 0, visible: false }
]

Comments

1

this is code to destroy and reset datatable

if ($.fn.DataTable.isDataTable("#categoryListDataTable"))
{
    $("#categoryListDataTable").dataTable().fnDestroy();
}

var table = $('#categoryListDataTable').DataTable( {
    rowReorder: true,
} );


table.on( 'row-reorder', function ( e, diff, edit ) {
    var res = '';
    for ( var i=0, ien=diff.length ; i<ien ; i++ ) {
        res += diff[i].newData+'=';
    }
    res = res.substring(0, res.length - 1);
    getVal(res);
} );

made this another function due to getting values and run ajax to save at server side

function getVal(res)
{
    var atmp = res.split('=');
    var newId = '';
    var newArr = [];
    for(var i=0,j=atmp.length;i<j;i++)
    {
        newId = $('#categoryListDataTable').find("tr:eq("+atmp[i]+") input[type='hidden']").val();
        if(newId != '')
            newArr[atmp[i]] = newId;
    }

    var urlStr = '<?php echo base_url('admin/managecategories/reorderCategories');?>';
    $.ajax({
        data:{new_:newArr},
        url:urlStr,
        cache:false,
        method:'POST',
        success:function(data){
            console.log(data);
        },
        error:function(error){
            console.log(error);
        }
    });
}

2 Comments

hope this will help you in problem
Welcome to stack overflow! Could you add a bit more description to this answer? The best answers normally have text that describes what the code is doing.
0

This is getting a bit aged, but I had to work through it and thought I'd share what I did. My requirements had this a table with sortable rows, but ordering by header click was not a requirement and made the UI a bit confusing.

The HTML is a fairly standard table.

HTML

<table class="table table-responsive-md table-striped" id="maskEditTable">
<thead>
    <tr>
        <th>Position</th>
        <th>Valid Characters</th>
        <th>Is&nbsp;Literal&nbsp;Character</th>
    </tr>
</thead>
<tbody>
    <tr>
        <td>0</td>
        <td><input type="text" class="form-control" value="123" /></td>
        <td>
            <label aria-label="Is Character Literal" for="needsAUniqueId"></label>
            <input type="checkbox" id="needsAUniqueId" />
        </td>
    </tr>
    <tr>
        <td>1</td>
        <td><input type="text" class="form-control" value="456" /></td>
        <td>
            <label aria-label="Is Character Literal" for="needsAUniqueId"></label>
            <input type="checkbox" id="needsAUniqueId" />
        </td>
    </tr>
    <tr>
        <td>2</td>
        <td><input type="text" class="form-control" value="789" /></td>
        <td>
            <label aria-label="Is Character Literal" for="needsAUniqueId"></label>
            <input type="checkbox" id="needsAUniqueId" />
        </td>
    </tr>
    <tr>
        <td>3</td>
        <td><input type="text" class="form-control" value="abc" /></td>
        <td>
            <label aria-label="Is Character Literal" for="needsAUniqueId"></label>
            <input type="checkbox" id="needsAUniqueId" />
        </td>
    </tr>
    <tr>
        <td>4</td>
        <td><input type="text" class="form-control" value="def" /></td>
        <td>
            <label aria-label="Is Character Literal" for="needsAUniqueId"></label>
            <input type="checkbox" id="needsAUniqueId" />
        </td>
    </tr>
</tbody>

The javascript is also fairly straight forward. The major difference is the addition of a draw event handler. This iterates the header fields and strips the class tag, and also removes the click handler. This code was called from a page onload hander.

JAVASCRIPT

function removeSorting() {
    $.each($('#maskEditTable').find('thead > tr > th'), function (i, header) {
        $(header).attr('class', null);
        $(header).off('click');
    });
}
function() init(){
    var tab = $('#maskEditTable')
        .DataTable({
        paging: false,
        info: false,
        searching: false,
        rowReorder: {
            selector: 'tr',
            update: true
        },
        order: [[0, "asc"]],
        columnDefs: [
            {
                targets: 0,
                visible: true
            }
        ]
        });
    tab.on('draw.dt', removeSorting);
    removeSorting();
}

The results are exactly what I was expecting and there is no visible effects on the redraw in any of my tests.

GL!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.