Draw (and other) events not firing when data is loaded by Javascript variable

Draw (and other) events not firing when data is loaded by Javascript variable

Loren MaxwellLoren Maxwell Posts: 406Questions: 99Answers: 10

I have two identical tables except that one uses an ajax call to load the data and the other uses a Javascript variable for the data.

I want to each of them to be hidden if there's no data in the table, so I've added the following on API method to both:

$(function() {
    var table = $("#table").DataTable({

        yada yada yada

    }).on("draw", function() {
        if (!table.data().any()) {
            $("#table_wrapper").children().hide();
        } else {
            $("#table_wrapper").children().show();
        }
    });
});

This works for the ajax-sourced table, but it doesn't seem the draw event occurs for the Javascript variable-sourced table. I've also tried the init event and the processing event, etc, but none work.

By inserting a console.log("drawing"); line I've verified the JS variable-sourced table never enters the on("draw") function at all.

Does this work correctly or should I be looking at a different event that would work?

Code for the ajax-sourced Datatable:

$(function() {
    var table = $("#table").DataTable({
        "paging": false,
        "autoWidth": true,
        "columnDefs": [{
            "targets": "_all",
            "render": $.fn.dataTable.render.text(),
            "searchPanes": {
                "show": false
            }
        }],
        "ajax": {
            "url": "/wiki/extensions/GHSFHA/models/mRegionPlayoffGames.php",
            "data": {
                "season": "2020",
                "organization": "GHSA",
                "class": "AAAA",
                "region": "5"
            }
        },
        "columns": [{
            "data": "game_type",
            "name": "game_type"
        }, {
            "data": "game_date",
            "name": "game_date"
        }, {
            "data": "playoff_game",
            "name": "playoff_game"
        }, {
            "data": "playoff_game_score",
            "name": "playoff_game_score"
        }],
        "ordering": false,
        "searching": false,
        "info": false,
        "dom": "tri"
    }).on("draw", function() {
        console.log("drawing");
        if (!table.data().any()) {
            $("#table_wrapper").children().hide();
        } else {
            $("#table_wrapper").children().show();
        }
    });
});

For the JS variable-sourced Datatable:

var table_data = [];
$(function() {
    var table = $("#table").DataTable({
        "paging": false,
        "autoWidth": true,
        "columnDefs": [{
            "targets": "_all",
            "render": $.fn.dataTable.render.text(),
            "searchPanes": {
                "show": false
            }
        }],
        "columns": [{
            "data": "game_type",
            "name": "game_type"
        }, {
            "data": "game_date",
            "name": "game_date"
        }, {
            "data": "playoff_game",
            "name": "playoff_game"
        }, {
            "data": "playoff_game_score",
            "name": "playoff_game_score"
        }],
        "ordering": false,
        "searching": false,
        "info": false,
        "dom": "tri",
        "data": table_data
    }).on("draw", function() {
        console.log("drawing");
        if (!table.data().any()) {
            $("#table_wrapper").children().hide();
        } else {
            $("#table_wrapper").children().show();
        }
    });
});

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,311Questions: 26Answers: 4,948
    Answer ✓

    I think the issue is the order of events (for lack of a better word) :smile: With Ajax loaded data its async so while waiting for the response Javascript continues running, instantiating the draw event. But with JS or DOM sourced data the Datatables initialization is synchronous and complete before instantiating the draw event.

    I think drawCallback should work. Or you can do something like this:

        var table = $("#table")
            .on("draw.dt", function() { ... })
            .DataTable({ ... });
    

    Note I think you will need the .dt for the Datatables namespace.

    Kevin

  • Loren MaxwellLoren Maxwell Posts: 406Questions: 99Answers: 10
    edited April 2020

    Thanks, @kthorngren. I tried the drawCallBack option. As before, worked with ajax-sourced data but not with Javascript variable-sourced data:

    var table_data = [];
    $(function() {
        var table = $("#table").DataTable({
            "paging": false,
            "autoWidth": true,
            "columnDefs": [{
                "targets": "_all",
                "render": $.fn.dataTable.render.text(),
                "searchPanes": {
                    "show": false
                }
            }],
            "columns": [{
                "data": "game_type",
                "name": "game_type"
            }, {
                "data": "game_date",
                "name": "game_date"
            }, {
                "data": "playoff_game",
                "name": "playoff_game"
            }, {
                "data": "playoff_game_score",
                "name": "playoff_game_score"
            }],
            "ordering": false,
            "searching": false,
            "info": false,
            "dom": "tri",
            "data": table_data,
            "drawCallBack": function() {
                if (!table.data().any()) {
                    $('#table').children().hide();
                } else {
                    $('#table').children().show();
                }
            }
        })
    

    Didn't try the other method yet, but I'd like to see if I can keep it to a more elegant solution that would be more intuitive when reading it.

  • Loren MaxwellLoren Maxwell Posts: 406Questions: 99Answers: 10

    Actually, let me update this -- the drawCallBack option doesn't work for the ajax-loaded data either.

  • Loren MaxwellLoren Maxwell Posts: 406Questions: 99Answers: 10

    Waitaminute! I was using drawCallBack instead of drawCallback.

    I'm testing, so I'll post back later with the final solution for posterity's sake.

  • Loren MaxwellLoren Maxwell Posts: 406Questions: 99Answers: 10

    Here was the final code:

    var table_data = [];
    $(function() {
        var table = $("#table").DataTable({
            "paging": false,
            "autoWidth": true,
            "columnDefs": [{
                "targets": "_all",
                "render": $.fn.dataTable.render.text(),
                "searchPanes": {
                    "show": false
                }
            }],
            "columns": [{
                "data": "game_type",
                "name": "game_type"
            }, {
                "data": "game_date",
                "name": "game_date"
            }, {
                "data": "playoff_game",
                "name": "playoff_game"
            }, {
                "data": "playoff_game_score",
                "name": "playoff_game_score"
            }],
            "ordering": false,
            "searching": false,
            "info": false,
            "dom": "tri",
            "data": table_data,
            "drawCallBack": function() {
                if (!this.api().rows().data().any()) {
                    $('#table').children().hide();
                } else {
                    $('#table').children().show();
                }
            }
        })
    

    Thanks, Kevin!

This discussion has been closed.