Potential Bugs: DT 1.11.4 - ColReorder 1.5.5 - Select 1.3.4

Potential Bugs: DT 1.11.4 - ColReorder 1.5.5 - Select 1.3.4

rf1234rf1234 Posts: 3,021Questions: 88Answers: 421
edited February 2022 in DataTables 1.10

Just a few days ago I downloaded new sources from the Download Builder. In particular I migrated from
- DT 1.10.21 to 1.11.4
- ColReorder 1.5.2 to 1.5.5
- Select 1.3.1 to 1.3.4
- Editor (with PHP Backend): 1.9.3 to 2.0.6

I had a couple of problems that I could only resolve by turning off "ColReorder" and "stateSave". Another issue regarding RowCallback I coulnd't resolve at all.

COLREORDER:
I used the Chrome debugger and saw that the child data table is simply “undefined”. The parent and child tables should be run on page load. They are not wrapped into functions. Just like in this example which had been my starting point: https://datatables.net/blog/2016-03-25
That is the message in the console:

Under “sources” I see this in Chrome:

Which is caused here because table() is read from an empty object:

Called from here:

Getting rid of ColReorder solved the problem for me.

STATESAVE:
I noticed that the "deselect" event was triggered on page load which didn't happen before. This lead to an attempt to reload a couple of child data tables which partly didn't exist yet.

This time there is nothing in the console but I can see everything relevant under “sources”.
Something undefined is passed to this function (“Cannot read properties of undefined”):

It is called from here. The last two tables passed were “undefined”. What puzzles me really is that “deselect” is triggered on page load.

If I look at the code of the DT select extension version 1.3.4 I see that the code executes a "deselect()" when loading the state. This of course triggers my dt event handler - and I end up having my "on deselect" code executed on page load:

Solution: turn off state saving!

I will open another thread for the rowCallback problem.

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,443Questions: 26Answers: 4,974

    I noticed that the "deselect" event was triggered on page load which didn't happen before. This lead to an attempt to reload a couple of child data tables which partly didn't exist yet.

    When are you creating those events? Before or after the child table is created?

    If you view the source code of the blog you linked you will see all the event handlers are created after both Datatables are initialized.

    Kevin

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421
    edited February 2022

    I create them before. That had never been relevant up to now. All that mattered was when the event handler was triggered. In all versions up to 1.9.3 since 2017 it didn't matter. If it matters now this is pretty much a disaster for me because I will have to rework tons of code - or I will need to do without state saving and possibly future releases :cold_sweat:

    And I am not sure whether this would work:
    If I create the event handlers after the data table initialization code has been run I cannot be sure that initialization has been completed - unless I use the "init" event. That is not in the example.

    In this case in which "deselect" is triggered by new DT code there is no guarantee the trigger from the new DT code will come before my event handlers will have been created.

    Another question: To make sure everyhting runs in sequence I would need to use the "init" event. But how do I know whether DT initialization won't trigger the "init" event in the future? It does trigger the "deselect" event now during initialization ...

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421
    edited February 2022

    One thing I forgot: If I have to assume that there are no changes being made following my request I will run into problems even using the "init" event. I have half a dozen child tables on this page. I could only set up the "deselect" and other event handlers for all of those tables after the initialization is completed for everything.

    Can the "init" event be set up with an array of data tables so that it gets triggered only after all of these tables are initialized?

  • allanallan Posts: 63,678Questions: 1Answers: 10,498 Site admin

    Sorry - I haven't fully taken all of this in yet, so I'll come back to it when I've got my thinking head on, but I can answer this:

    Can the "init" event be set up with an array of data tables so that it gets triggered only after all of these tables are initialized?

    No. It is fired for each table as it is created, and since Javascript is single threaded they are sequential. If you want to store them up, you'd need to have a buffer for that and also know when they are finished so you can run all of them together.

    Allan

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421
    edited February 2022

    Thanks for that, Allan. Basically the only problem is that now the "deselect" event is triggered by the new DT code above even though the users didn't deselect anything. That's the only thing important to me - and I'd be very happy if this could be changed. (I think the same applies to the "select" event.)

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421

    I applied a hack to the select extension like this in order to avoid unrequired deselects and now it works. Only the selected rows, columns and cells are now deselected. See "change rf1234" below.

    Can you take a look and fix it in the select extension for the next release please.

    DataTable.select.version = '1.3.4';
    
    DataTable.select.init = function ( dt ) {
        var ctx = dt.settings()[0];
    
        if (ctx._select) {
            return;
        }
    
        var savedSelected = dt.state.loaded();
    
        var selectAndSave = function(e, settings, data) {
            if(data === null || data.select === undefined) {
                return;
            }
            // dt.rows().deselect();
            // dt.columns().deselect();
            // dt.cells().deselect();
                    //change rf1234
            dt.rows({selected:true}).deselect();
            dt.columns({selected:true}).deselect();
            dt.cells({selected:true}).deselect();
                    //end change rf1234
            if (data.select.rows !== undefined) {
                dt.rows(data.select.rows).select();
            }
            if (data.select.columns !== undefined) {
                dt.columns(data.select.columns).select();
            }
            if (data.select.cells !== undefined) {
                for(var i = 0; i < data.select.cells.length; i++) {
                    dt.cell(data.select.cells[i].row, data.select.cells[i].column).select();
                }
            }
            dt.state.save();
        }
        
        dt.one('init', function() {
            dt.on('stateSaveParams', function(e, settings, data) {
                data.select = {};
                data.select.rows = dt.rows({selected:true}).ids(true).toArray();
                data.select.columns = dt.columns({selected:true})[0];
                data.select.cells = dt.cells({selected:true})[0].map(function(coords) {
                    return {row: dt.row(coords.row).id(true), column: coords.column}
                });
            })
            
            selectAndSave(undefined, undefined, savedSelected)
            dt.on('stateLoaded stateLoadParams', selectAndSave)
        })
    

    I got the latest versions from the download builder again and got rid of some extensions I didn't use or I couldn't get working like rowReorder, colReorder, Scroller etc.. Runs a lot faster now.

  • allanallan Posts: 63,678Questions: 1Answers: 10,498 Site admin
    Answer ✓

    Super - thanks for the analysis! I've committed a fix for the error. Not sure if it is any faster or not than your solution, but they do basically the same thing.

    The nightly will be up to date with the change shortly.

    Allan

Sign In or Register to comment.