Bug responsive.hasHidden()

Bug responsive.hasHidden()

rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
edited April 2020 in Responsive

responsive.hasHidden() only returns false if
- you have no columns hidden by responsive AND
- the table would not have hidden columns if column visibility was set to true for all columns.

In other words it returns false if your table has few columns and regardless of colvis has no columns hidden by responsive.

But if you hide a few columns with the colvis button so that nothing is hidden by responsive ( but would have been hidden if nothing was hidden by colvis ): It does not work. It will return true.

responsive.hasHidden() seems to "count" the columns hidden by colvis as well which it shouldn't. Right now it is not usable for me because I always have at least one column hidden by colvis!

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    Hi,

    Thanks for posting this up - I've just created a little test case which appears to work as expected: http://live.datatables.net/jociciha/1/edit . If you hide a column using the buttons and then click the button, it should correctly report Responsive hasn't hidden any columns (assuming the screen is wide enough!).

    Are you able to modify that example to make it show the issue you are seeing?

    Regards,
    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    Hi Allan,

    your example works perfectly fine - and I am unable to change the example so that it doesn't work because I wouldn't know how. I must have a very special situation I guess ... I will try to figure it out. If I can't figure it out I will send you login credentials so that you can see the behavior on my pages. Thanks.

    Roland

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    I tried to add an event to show the effect but the event doesn't get triggered in the example. No idea why it doesn't get triggered. It works perfectly on my own pages.

    http://live.datatables.net/visijuta/1/edit

  • kthorngrenkthorngren Posts: 21,321Questions: 26Answers: 4,948
    edited April 2020

    Using the column-visibility event shows the issue.
    http://live.datatables.net/negikucu/2/edit

    Hiding the first column shows false hiding the second shows true.

    EDIT: I used Download Builder to get the code. Not sure what else is different.

    Kevin

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
    edited April 2020

    Hi Kevin and Allan,

    I used your example now Kevin and tried it with column visibility. The event got triggered 6 times. Once after loading then another 5 times after hiding 5 columns subsequently. After hiding the 3rd or the 4th column responsiveHasHidden should have returned "false" but it never did!

    My problem is even bigger: I load the state and for some users it is less columns than for others. This doesn't work either. I could live with it not working on dynamic column visibility changes but it doesn't work for initial state-loaded columns either.

    I tried all the events that could seem relevant. It never worked - just like with column-visibility.

    Then I did the same with "responsiv-resize" which only got triggered for the 2nd time when there was only one column left. Same result:

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    This absolutely amazing: I triggered Allan's button click with setInterval every 3 seconds and in parallel used the colvis button manually down to just one visible button. Now BOTH console logs return true, also the button click when there was only one column visible! Weird.
    http://live.datatables.net/yeposiyo/1/edit

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
    edited April 2020

    And another one ...
    Just using setInterval with the button click every 3 seconds and without the colvis event worked! So the colvis event handler seems to interfere with the click event?!
    Now you understand why I think front end programming is a bad nightmare. :smile:
    http://live.datatables.net/powiwuzi/1/edit

    Here you are:

    But hey: I got a work around now. No dt event but a click on a hidden button or something :smiley:

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
    edited April 2020

    I tried these work arounds to avoid calling responsive.hasHidden() from within a dt event handler. They didn't work either with tables that had their columns hidden by state saving and hence had no columns hidden by responsive. So no workaround for me :neutral:

    The response in my debugger was always that responsive.hasHidden is true even though it should have been false.

    1st Workaround:

    var interval = setInterval(function () {
        if ($('#tblContractGov').is(':visible')) {
            clearInterval(interval);
            setTimeout(function() {
                if ( ! contractTable.responsive.hasHidden() ) {
                    contractTable.buttons("showHideAllChildRowsButton:name").nodes().addClass('hidden');
                } else {
                    contractTable.buttons("showHideAllChildRowsButton:name").nodes().removeClass('hidden');
                }
            }, 5000);        
        } },
        100
    );
    

    2nd Workaround:

    var maxTime = 30000, 
        startTime = Date.now();
    
    var interval = setInterval(function () {
            if ($('#tblContractGov').is(':visible')) {
                if ( ! contractTable.responsive.hasHidden() ) {
                    contractTable.buttons("showHideAllChildRowsButton:name").nodes().addClass('hidden');
                } else {
                    contractTable.buttons("showHideAllChildRowsButton:name").nodes().removeClass('hidden');
                }
            } else {
                if (Date.now() - startTime > maxTime) {
                    clearInterval(interval);
                }
            }
        },
        1000 
    );
    
    
  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin
    Answer ✓

    It looks like something that has been fixed but not yet released - I can see the issue in Kevin's version using the CDN releases as well, but when using the nightlies it works as expected.

    This is the commit that fixed it.

    I'll do a Responsive release along with Editor around the end of the month.

    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    I'll wait for the Editor and Responsive releases then. Thanks Allan.

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    I installed the new versions today: And the bug was not fixed unfortunately. The same behavior as before: If you have columns hidden through colvis it is not working! responsive.hasHidden() does not recognize that there aren't actually any columns hidden by the responsive extension in this case.

    The whole thing only works if you don't use changes through colivs that are state saved. That is not good enough for me. I cannot use this and I am giving up now.

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    I've just tried updating the test case that Kevin kindly put up before, to use the current releases: http://live.datatables.net/negikucu/7/edit . It seems to work as I would expect - hide a couple of columns so that Responsive is not hiding any columns itself, click the button and the console will show false as Responsive has not hidden anything.

    Is that not happening for you?

    Thanks,
    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
    edited May 2020

    Yes it works in your example and also for me when using the "column-visibility" event. Unfortunately that is not enough for my use case. I need to hide and show a button that allows the user to show / hide all of the child rows of the respective page and that depends on the screen size, on colvis etc. and changes of the screen size, colvis etc.

    It is rather a problem of finding all of the required events and in this case unfortunately: it seems to be a multitude of potentially suitable events.

    I tried this code:

    contractLogTable
        .on( 'draw', function () {
            var self = contractLogTable;
            if ( self.responsive.hasHidden() && self.data().count() ) {
                self.button('showHideAllChildRowsButton:name').nodes().removeClass('hidden');
            } else {
                self.button('showHideAllChildRowsButton:name').nodes().addClass('hidden');
            }
        })
        .on( 'column-visibility', function () {
            var self = contractLogTable;
            if ( self.responsive.hasHidden() && self.data().count() ) {
                self.button('showHideAllChildRowsButton:name').nodes().removeClass('hidden');
            } else {
                self.button('showHideAllChildRowsButton:name').nodes().addClass('hidden');
            }
        })
        .on( 'reponsive-resize', function () {
            var self = contractLogTable;
            if ( self.responsive.hasHidden() && self.data().count() ) {
                self.button('showHideAllChildRowsButton:name').nodes().removeClass('hidden');
            } else {
                self.button('showHideAllChildRowsButton:name').nodes().addClass('hidden');
            }
        })
        .on( 'reponsive-display', function () {
            var self = contractLogTable;
            if ( self.responsive.hasHidden() && self.data().count() ) {
                self.button('showHideAllChildRowsButton:name').nodes().removeClass('hidden');
            } else {
                self.button('showHideAllChildRowsButton:name').nodes().addClass('hidden');
            }
        })
    

    The "draw" event:
    - Works for the initial draw and redraw. Does not work when gradually hiding / showing more and more columns through colvis

    The "column-visibility" event:
    - Works when gradually hiding / showing more and more columns through colvis

    The "responsive-resize" and "responsive-display" events:
    - Should work when resizing the columns and / or the screen so that columns are hidden / unhidden by the responsive extension: But do not work at all.

    Could you recommend an event that covers all of my use cases? If not: How can I get the "responsive" events going?

    P.S.: Here is the definition of the button that needs to be dynamically shown or hidden depending on whether or not child rows exist:

    //custom button to show all child rows of the rows selected (responsive extension)
    $.fn.dataTable.ext.buttons.showHideAllChildRows = {
        text: showHideAllChildRowsSelectedLabel,
        name: "showHideAllChildRowsButton",
        action: function ( e, dt, button, config ) {
            // https://www.gyrocode.com/articles/jquery-datatables-how-to-expand-collapse-all-child-rows/
            //dt.rows( ':not(.parent)', { selected: true } ).nodes().to$().find('td:first-child').trigger('click');
            $.busyLoadFull("show", { 
                fontawesome: "fa fa-spinner fa-spin fa-3x fa-fw"
            });
            var selParent;
            if ( dt.rows( ':not(.parent)', { page: 'current' } ).count() > 
                 dt.rows( '.parent',       { page: 'current' } ).count()    ) {
                selParent = ':not(.parent)';
            } else {
                selParent = '.parent';
            }
            setTimeout(function() {
                var sel = dt.rows( selParent, { page: 'current' } ).nodes().to$();
                //also possible: sel.find('td:first-child').trigger('click'); 
                //               sel.promise()done(function ...
                sel.find('td:first-child').trigger('click').promise().done(
                    function(){
                        $.busyLoadFull("hide", { 
                          // options here 
                        });
                    } )
            }, 50);
        }
    };
    
  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    As you say, you are going to need to use a combination of events here, since there isn't one event to rule them all (a column visibility change doesn't need to do a draw for example).

    One thing to point out first is that you can listen for multiple events with a single handler - e.g.:

    contractLogTable.on( 'draw.dt column-visibility.dt reponsive-resize.dt reponsive-display.dt', function () {
        ...
    });
    

    That will help reduce the code a bit.

    Should work when resizing the columns and / ore the screen so that columns are hidden / unhidden by the responsive extension: But do not work at all.

    I've just tried that in a little test case: http://live.datatables.net/vihihaca/1/edit . It does appear to work there. Can you modify it or create one that shows the issue?

    Thanks,
    Allan

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421

    Hi Allan, I tried the same in parallel and actually "responsive-resize" worked as well. So the problem would be solved ...

    But: In my code "responsive-resize" never gets triggered :neutral:

    Otherwise the responsive extension works perfectly fine. I disabled stateSaving and tried a few other things: Didn't help.

    Would you have any idea what could cause this?

    Roland

    P.S.: Thanks for the hint with the multiple events in one handler. I wasn't aware of this and usually put all of the redundant code in little helper functions ...

  • rf1234rf1234 Posts: 2,988Questions: 87Answers: 421
    edited May 2020

    Oh sh... I'm such a freakin' idiot :neutral:

    "reponsive-resize" doesnt work of course. It should be "responsive-resize".

    Thanks Allan, for your patience! I owe you a beer or two!

    This is my final code that works for all of my use cases:

    contractLogTable
        .on( 'draw column-visibility responsive-resize', function () {
            var self = contractLogTable;
            if ( self.responsive.hasHidden() && self.data().count() ) {
                self.button('showHideAllChildRowsButton:name').nodes().removeClass('hidden');
            } else {
                self.button('showHideAllChildRowsButton:name').nodes().addClass('hidden');
            }
        })
    

    That's one of the few things that was better in the good old days of COBOL and the like: You had a typo and you got a compiler error - no endless searching for stuff like this ... Lots of typing writing COBOL though - but in demand again these days :smiley:

  • mhamzaibmhamzaib Posts: 1Questions: 0Answers: 0
    edited August 2020

    Hi,
    I wanted to discuss a similar issue regarding this. I'm trying to place the responsive icon on the right side instead of the left, and want the data in the first column to be hidden by default (Here's how I'm doing this, I cloned and modified Allan's example above). But this implementation returns true every time even when it's not in responsive mode. Am I doing something wrong here?

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    Interesting - it is because of the use of:

          details: {
              type: "column",
              target: -1,
            },},
    

    That means that there will always be a column hidden! Either the table is in its collapsed state (the control column is visible and one or more of the other columns are hidden), or it is in the uncollapsed state (where the control column is hidden, but the other columns are not!).

    I think the easiest way to find out here is going to be to check for the collapsed class on the table: http://live.datatables.net/quyepeza/2/edit .

    Allan

This discussion has been closed.