Possible bug in ColVis button

Possible bug in ColVis button

pain19pain19 Posts: 42Questions: 5Answers: 0

Just curious if anyone else has reported this. It's not huge for me as I can keep using the older version, but it's always nice to ensure all libs are on their latest versions to ensure compatibility.

When I use 1.7.1 for DT buttons, everything works just fine when I change columns (show/hide) and refresh/reload my table. However, when I use version 2.2.2, it breaks this functionality.

I receive the following error message: TypeError: undefined is not an object (evaluating 'c.offset().top)

I'm be putting together a test case to try and reproduce the issue I am seeing. But my guess is, with the latest version, there's something my code isn't handling. For example, I had to update my refresh code to destroy the button container as the latest version was making a copy of the buttons whereas it didn't do this before.

This question has accepted answers - jump to:

Answers

  • colincolin Posts: 15,112Questions: 1Answers: 2,583

    We're not aware of anything that would break between those versions. Both your issues, the error message and the need to destroy, we wouldn't have expected.

    I've knocked out this test case with a single button - could you describe how we could see those two issues using that, please?

    Thanks,

    Colin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    @Colin I made a copy of what you have and modified as best as I could towards my example: http://live.datatables.net/sikufuvi/1/edit?html,css,js,output

    `$(document).ready( function () {
    var table = $('#example').DataTable({
    dom: 'Bfrtip',
    buttons: [
    "colvis",
    {
    "text": 'Refresh',
    "action": function (e, dt, node, config) {
    if ($.fn.dataTable.isDataTable("#")) {
    // Show a spinner in case this process takes a long time.
    this.processing(true);

              // If checkbox header is selected, remove the proper classes.
              $(".toggle-all-projects").closest("tr").removeClass("special");
              $(".toggle-all-projects").closest("tr").removeClass("selected");
    
              // Remove the click event so it will reset properly once table is recreated.
              $("#example").off('click');
    
              // Be sure to empty the table of any leftover rows.
              $("#example").empty();
    
              // Destroy the instance of the buttons so they are not redrawn.
              table.buttons().destroy();
    
              // Set the redraw tracker to true so the table is properly drawn.
    
              // Call the method to redraw/refresh the table.
           }
        }
      }
    ]
    

    });
    } );`

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    I'm seeing this error when clicking the Refresh button:

    Uncaught Error: Syntax error, unrecognized expression: #

    I changed this:

    if ($.fn.dataTable.isDataTable("#")) {
    

    to this:

    if ($.fn.dataTable.isDataTable("#example")) {
    

    And now the Refresh button seems to work. At least its not generating any errors :smile:

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

    Can you provide the steps needed to see this error?

    TypeError: undefined is not an object (evaluating 'c.offset().top)

    Kevin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    Basically, I have a row of buttons in my app that includes ColVis and a custom refresh button. The table's data is drawn from Jira via Atlassian's REST API.

    With ColVis on v1.7.1, I can change the visible columns and hit my refresh button and it redraws everything as expected. This is done in case new data was added to Jira while looking at the table in my app. Instead of hitting the browser refresh, I added it directly on the tables.

    With ColVis 2.2.2, when I change the columns and hit my refresh button I get the error I described above. With 2.2.2, I fixed the copying of the buttons using destroy(). I did not have to do this before.

    So, with updating to the newer libs I am sure I am missing something to ensure it works or I may need to recode something that I did incorrectly that wasn't being caught before.

    Either way, I "never" blame DT because it has been ROCK SOLID for me since I started using it in 2020. All errors have always been on my end. :)

  • pain19pain19 Posts: 42Questions: 5Answers: 0
    edited February 2022

    @kthorngren sorry that was a typo on my part. I tried to walkthrough the steps above for my specific case. My biggest issue is, I can "never" reproduce my issue outside of my app. LOL.

    Basically, when the table is created, I am fetching data via an API for Jira. From there, I build the table and all is well. With 1.7.1, The refresh code (listed above), simply emptied the table, turned off any selections, etc. and then recalled the setup function which goes out, grabs the data again in case there were any updates, and redraws the table.

    If I point to ColVis 1.7.1, this all works perfectly. When I point to 2.2.2, that's when I get the error. Maybe, I'm not fully destroying everything--just need to find out what it is.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited February 2022

    Hmm, not sure. Looks like you have removed code for redrawing the table. Please post all the code for that function.

    What click event are you trying to remove?

                  // Remove the click event so it will reset properly once table is recreated.
                  $("#example").off('click');
    

    I suggest moving this as the last thing you do after removing any Datatables specific items such as using destroy().

                  // Be sure to empty the table of any leftover rows.
                  $("#example").empty();
    

    Kevin

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    Sounds like you might be rebuilding the table from scratch in your function to fetch from the API. Maybe you just want some thing like this:
    http://live.datatables.net/sanuvoso/1/edit

    First it uses destroy() then empties the table with $("#example").empty();.

    Kevin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    @kthorngren unfortunately, the redrawing code is lengthy because it involves accessing another API. I'll add that as a last resort as I think in the refresh I am not taking care of something. If the table draws initially AND I can hit my refresh button and redraw with no issues, I don't think that code matters. It's only when I change the columns and refresh that something is going wrong. So, I'm focusing there and will dig deeper.

    One thing I noticed in the console is I'm using jquery-3.6.0. Most examples seems to be using query-3.5.1. So I will go back to 3.5.1 and see if that helps. Could be I'm using incompatible versions.

  • pain19pain19 Posts: 42Questions: 5Answers: 0
    edited February 2022

    Oh and to answer your question, I have a checkbox row that allows users to select the rows. I also have the checkbox in the header row for a "select all" and use a button to "select all current page". As I am redrawing the table, I am cleaning up any selected or showing of the detail rows.

    Updated note: I'm trying to upload screenshots so you have a visual but it is not allowing to do so.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    jQuery version shouldn't matter.

    the redrawing code is lengthy

    Are you reinitializing Datatables in this function or just rebuilding the HTML table. Understanding this process might help. If you are hiding a column then just simply rewriting the HTML table then I can see an error being generated.

    Kevin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    @kthorngren ok, I had my my destroy after my empty, but using this example: https://datatables.net/reference/api/destroy()

    I put my destroy before my empty and that seems to work--although it gets rid of my headers and the click functionality, but that's another issue. LOL.

    As always, thanks for the assist!

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    although it gets rid of my headers and the click functionality, but that's another issue. LOL.

    destroy() will remove any event handlers it has bound but if you created others they won't be removed. It supposed to leave the HTML table in its original state. The $("#example").empty(); will remove the HTML table, headers and all.

    Kevin

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    How are you loading the table data from the API?

    Kevin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    @kthorngren ok so I have to figure out what's going on with my app when I try to use fixedHeader or a scrollX/scrollY window.

    I reset my app back to it's original state and turned on the latest libs (including ColVis 2.2.2) and it works perfectly.

    The app has been in the wild since 2020 and no one has complained about not having a fixed header, so I'll take my time and go through the code more thoroughly. But for now (and tomorrow's demo), I should be fine with what I have since it is more of an incremental update versus adding new functionality and trying to make it sexier. >:)

    The only issue I'm having with fixedHeader: true is that it seems to lose the table's column settings. I had another thread where I got this working, but the solution seems to break something else. Lol.

    But again, if I don't set column widths at all, I get funky column widths, but fixedHeader: true works just fine. So I need to dig and figure out where I am losing the column widths. It may be like you stated where I need to use destroy() instead of empty().

    No worries, if I figure it all out, I'll be sure to post the solution. Thanks for the help!

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    Quick update. So it seems my issue is that the initial fixedHeader is being stored and when I refresh the table, I am not updating it or destroying it properly. I've searched the forums and have only found custom methods for destroying the fixed header but those solutions do not resolve my issue. I also tried to use fixedHeader.disable(), columns.adjust(), and fixedHeader.adjust(), but none have resolved the issue.

    Goal: Start using fixedHeader for clients that produce thousands of rows in the tables.

    Test cases:
    * fixedHeader false: Redraws just fine with and without column toggling (show/hide).
    * fixedHeader true, no column toggles: Successfully redraws.
    * fixedHeader true, column toggling: Fails to redraw

    Pseudo code to explain posted code.
    1. First thing I do is sow the spinner for progress.
    2. Next I remove the classes for selected rows, note that special is nothing special so don't worry about that at all.
    3. Then I remove the click event so if the user selected something before refreshing the table it simply ensure nothing is selected once the table has been redrawn.
    4. Next I have a tracker to determine if this is the first time the table is being drawn or a refresh.
    5. Then I empty the table.
    6. And finally, I call the method that re-grabs the data and redraws the table.

    ` {
    // Setup the button code and action.
    "text": '<i class="fa fa-refresh"></i>',
    "titleAttr": 'Refresh the table',
    "className": 'rw-button',
    "action": function ( e, dt, node, config ) {
    if ($.fn.dataTable.isDataTable("#projects")) {
    // Show a spinner in case this process takes a long time.
    this.processing(true);

                            // If checkbox header is selected, remove the proper classes.
                            $(".toggle-all-projects").closest("tr").removeClass("special");
                            $(".toggle-all-projects").closest("tr").removeClass("selected");
    
                            // Remove the click event so it will reset properly once table is recreated.
                            $("#projects").off('click');
    
                            // Destroy the instance of the buttons so they are not redrawn.
                            tableProjects.buttons().destroy();
    
                            // Set the redraw tracker to true so the table is properly drawn.
                            redrawProjects = true;
    
                            // Be sure to empty the table of any leftover rows.
                            $("#projects").empty();
    
                            // Call the method to redraw/refresh the table.
                            performProjectSetup(projectsBaseUrl);
                        }
                    }
                }],`
    
  • pain19pain19 Posts: 42Questions: 5Answers: 0

    Ok guys, please don't hurt me on this one. B)

    What I discovered is I had an old jquery line that was conflicting with the DT jquery reference. I also had to change my $("#projects").empty(); to tablesProjects.destroy(); And everything seems to be working per the test cases I provided before.

    One quick question, by using destroy() instead of empty(), as the refresh is taking place, it shows the mangled table data before it redraws. Is there a way to make sure things are Clea

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited February 2022 Answer ✓

    Take a look at the second example in the destroy() docs. It uses empty() after destroy(). As I mentioned above use empty() after you have used any Datatables methods to clean up the table.

    Kevin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    @kthorngren yep I tried that and I get some crazy results. But no worries, this is minor and based on the 2nd example, looks like I may need to split my code up differently. Nevertheless, thanks again for all your help. Which I would've done a jquery search days ago and saw what was causing me all my grief.

    Oh well, such is the life of a programmer---live and learn. LOL

  • pain19pain19 Posts: 42Questions: 5Answers: 0
    edited February 2022

    @kthorngren hey real quick, now that the refresh stuff is working I am experimenting with using scrollY to have a viewing window, which can essentially function as a fixed header. I've reviewed several examples and my table code matches:

    <table id="example" class="display" style="width:100%">

    I don't see anything else special yet my table will expand beyond the headers if I open the browser wide enough. And of course, if I turn off scrollY the tables and header/footer expand/shrink together.

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    I should note I am not using any special css for the table---only the defaults.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    Answer ✓

    Sounds like you are wanting horizontal scrolling using scrollX, like this example.

    Kevin

  • pain19pain19 Posts: 42Questions: 5Answers: 0

    @kthorngren I am using the example from here: https://datatables.net/examples/basic_init/scroll_y.html

    My issue is when the browser window is resized, the header adapts, but the table itself doesn't. Based on this example, I didn't see any special code that was needed to address this, so I thought it was odd. Of course, with no scrollY setting, it all works perfect.

    No worries. I am going to close out this thread and stop breaking the rules. I absolutely love what your guys have done with DT and the help you've given me. It is long past time for me to follow the rules you've established and I sincerely apologize for my continued abuse. Won't happen again. B)

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    That example is using "scrollY": "200px" which is setting the height of the table. From the scrollY docs:

    Vertical scrolling will constrain the DataTable to the given height, and enable scrolling for any data which overflows the current viewport.

    You might be interested in the ScrollResize plugin.

    Kevin

Sign In or Register to comment.