Search code examples
javascriptdatatablesmapbox

Datatables - after first button click the button is no longer responsive in each row. How to fix?


I have a datatable called skiTable. It consists of rows of ski mountains. In each row, there is a button called FlyTo with latitude and longitude (aa_x, aa_y). When clicked it zooms into the ski mountain using mapbox gl js (map.flyTo). Once the map is zoomed in, I then use map.queryRenderedFeatures() to return data to datatable of just the displayed mountain in aDemoItems. Sometimes there can be surrounding mountains and therefore the row count can be anywhere from 1 mountain to 10 mountains.

On the first initiation of the datatable, clicking the FlyTo button works fine, however, none of the buttons work after the first click. Dead. Here is the button's click event handler;

        $('#ski_index').on('click', 'button', function () {
            var data = skiTable.row($(this).parents('tr')).data();
            x = data.properties["aa_x"];
            y = data.properties["aa_y"]
            map.flyTo({center: [x, y], zoom: 15});
        });

Again, the data for the datatable comes via mapbox's map.queryRenderedFeatures() which is stringified (JSON.stringify(uniqueFeatures)) and passed to datatables as data: aDemoItems.

let skiTable =      $('#ski_index').DataTable({
            stateSave:      true,
            stateDuration:  60 * 60 * 48, // save the state for 2 days.
            responsive:     true,
            info:           true,
            destroy:        true,
            data:           aDemoItems,
            dataType:       'json', 
            "columns": [{
                    data: "properties.name",
                    "defaultContent": "<i>Not set</i>",
                    render: function (data, type, row){
                        return '<button>FlyTo</button>'
                    }
                }];
           });

Everything works well except any second click on the button FlyTo doesn't respond. As I zoom in and out of the map, the datatable shows only the ski mountains displayed. Any help much appreciated to get the button working from the second click.

I just realized this is a error message on the second click of the FlyTo button as follows;

Uncaught TypeError: Cannot read properties of undefined (reading 'properties')

If I add console.log(row) to the column definition as follows;

                {
                    data: "properties.name",
                    "defaultContent": "<i>Not set</i>",
                    render: function (data, type, row){
                        console.log(row);
                        return '<button>Click!</button>'
                    }
                },

... the console.log(row) does show properties with values in aa_x and and aa_y.


Solution

  • Try not to use the table destroy methods, which in my experience cause more problems than they solve, and are rarely needed unless you want to change some of the table structure, such as the number of columns.

    Instead make use of the ajax.reload() method to refresh the data in your table. You say that your data is coming from an external source, which likely means you cannot directly apply it to your table. To solve this, define your ajax property in the table options as a function like this (also store your table as a variable):

    let my_array = [];
    
    const skiTable = $('#ski_index').DataTable({
        ajax: function(data, callback) {
            callback({ data: my_array })
        }
    });
    

    Next grab your data, do whatever ajdustments you need to do to it, and store the results in my_array.

    my_array = some_new_data;
    

    Now you can call the reload() function to refresh the data in your DataTable

    skiTable.ajax.reload();