jQuery Datatables losing reference on pagination

jQuery Datatables losing reference on pagination

D3vD3v Posts: 10Questions: 2Answers: 0

I currently have a table that is generated server side (Table A). Clicking a row in Table A calls CreateTable(arrayData):

function CreateTable(arrayData){
var table = $('#tableB').DataTable({
destroy: true,
bFilter: false,
bLengthChange: false,
dt: "[-head|-body]-left",
"data": arrThemes,
"language": {
"paginate": {
"first": "First",
"last": "Last",
"next": "Next",
"previous": "Prev"
}
});

            $('#tableB tbody').on('click', 'tr', function () {
            //$("#tableB tbody tr").click(function (event) {
                if ($(this).hasClass('selected')) {
                    $(this).removeClass('selected');
                }
                else {
                    table.$('tr.selected').removeClass('selected');
                    $(this).addClass('selected');
                }
                var rowIdx = table.row(this).index();
                SetInfo(arrData[rowIdx], null);
            });

}

Pagination and row highlighting in Table B works fine when I first click on any row in Table A. However when I click on another row in Table A, row highlights in Table B stop working, and SetInfo() is somehow called twice. If I again select another row in Table A, SetInfo() is now called four times, then eight etc.

When I try using $("#tableB tbody tr").click(function (event) {...} (currently commented out) everything works as expected on page 1 of Table B, but not on any other pages - it doesn't seem to bind correctly.

Any idea what I might be doing wrong?

Answers

  • allanallan Posts: 61,726Questions: 1Answers: 10,110 Site admin

    Second top FAQ :-)

    Allan

  • D3vD3v Posts: 10Questions: 2Answers: 0

    I based my code on the example you mentioned, but I'm still having problems. The difference here is that I'm destroying and creating a new DataTable every time I click on a row in the parent table (Table A). Does 'destroy:true' remove everything from the DOM?

  • D3vD3v Posts: 10Questions: 2Answers: 0
    edited May 2016

    Using $("#tableB tbody tr").on("click", function () {..} solves a lot of the problems, but binding is still lost after the first page.

  • allanallan Posts: 61,726Questions: 1Answers: 10,110 Site admin

    The code you show above shows the use of a static event rather than a delegated one as suggested in the FAQ and the example it linked to.

    If you are using a delegated event and are still having problems, please link to the page showing the issue.

    Allan

  • D3vD3v Posts: 10Questions: 2Answers: 0

    Unfortunately I cannot provide a link. I know the code directly above isn’t correct, I was only using it as an example.
    The code actually in use is in the snippet at the top, where the static binding was commented out and replaced with the delegated binding as instructed by the FAQ.
    When I initially click on a row in Table A, everything in Table B works. When I click on another row in Table A (thus destroying and creating a new Table B) it tries to bind multiple times. For example, when I try something like $('#tableB tbody').on('click', 'tr', function () { alert('test!'); }); the pop-up is "test!". Clicking on another row in Table A will pop-up "test!" twice, then four times etc.

  • D3vD3v Posts: 10Questions: 2Answers: 0

    Another example that might shed some light on the issue - I've added the following:

    $('#TableB').on('draw.dt', function () {
    var info = table.page.info();
    console.log('Showing page: ' + (info.page + 1) + ' of ' + info.pages);
    });

    When I click on Table A, row 1, it creates Table B with 2 pages. Clicking on Table B page 2 outputs:

    "Showing page: 2 of 2"

    Next, I click on Table A, row 2, it destroys and recreates Table B with 7 pages. Clicking on Table B page 2 outputs:

    "Showing page: 2 of 2"
    "Showing page: 2 of 7"

    Clicking on Table B page 3 outputs:

    Showing page: 2 of 2"
    Showing page: 3 of 7"

    Clicking on Table B page 4 outputs:

    "Showing page: 2 of 2"
    "Showing page: 4 of 7"

    Next, I click on Table A, row 1 again. It destroys and recreates Table B with 2 pages. Clicking on Table B page 2 outputs:

    "Showing page: 2 of 2"
    "Showing page: 4 of 7"
    "Showing page: 2 of 2"

    Clicking on Table B page 1 outputs:

    "Showing page: 2 of 2"
    "Showing page: 4 of 7"
    "Showing page: 1 of 2"

    It's almost as though the destroyed tables are still somewhere in the DOM.

  • allanallan Posts: 61,726Questions: 1Answers: 10,110 Site admin

    Are you able to use JSFiddle, CodePen, http://live.datatables.net or any other code hosting service to create an example showing the issue so I can debug it please.

    Allan

  • D3vD3v Posts: 10Questions: 2Answers: 0

    Hi Allan - we figured it out. We put the binding in its own method and used the callback 'drawCallback':

    function CreateTable(arrayData){
    var table = $('#tableB').DataTable({
    destroy: true,
    bFilter: false,
    bLengthChange: false,
    dt: "[-head|-body]-left",
    "data": arrayOfData,
    "drawCallback": BindOnClick,
    "pageLength": 5,
    ....etc.
    });

    function BindOnClick() {
    //get the table object:
    var table = $('#tableB').DataTable();

        //set the row highlighting:
        $("#tableB tbody tr").on("click", function () {
            if ($(this).hasClass('selected')) {
                $(this).removeClass('selected');
            }
            else {
                table.$('tr.selected').removeClass('selected');
                $(this).addClass('selected');
            }
    
               //now call any method you want and pass in data
               //based on row index:
               var rowIdx = table.row(this).index();
               SetInfo(table.data()[rowIdx]);
        });
    

    }

  • D3vD3v Posts: 10Questions: 2Answers: 0
    edited May 2016

    Not sure why the formatting is off, but that's the idea.

  • allanallan Posts: 61,726Questions: 1Answers: 10,110 Site admin

    Thanks for posting back - good to hear you've got it working.

    Details on how to highlight code using markdown can be found in this guide.

    Allan

  • D3vD3v Posts: 10Questions: 2Answers: 0
    edited May 2016

    Updated method, otherwise you might get multiple bindings:

    function BindOnClick() {
    //get the table object:
    var table = $('#tableB').DataTable();
    
    //set the row highlighting:
    $("#tableB tbody tr").off("click").on("click", function () {
        if ($(this).hasClass('selected')) {
            $(this).removeClass('selected');
        }
        else {
            table.$('tr.selected').removeClass('selected');
            $(this).addClass('selected');
        }
     
           //now call any method you want and pass in data
           //based on row index:
           var rowIdx = table.row(this).index();
           SetInfo(table.data()[rowIdx]);
    });
    }
    

    Edited by Allan - Syntax highlighting. Details on how to highlight code using markdown can be found in this guide.

  • allanallan Posts: 61,726Questions: 1Answers: 10,110 Site admin

    Super - thanks for the update!

This discussion has been closed.