Bootstrap have to call columns.adjust twice for interrupted tab load

Bootstrap have to call columns.adjust twice for interrupted tab load

davedargodavedargo Posts: 10Questions: 2Answers: 0

I have a solution to the problem but if there's something else known I'd appreciate knowing it.

I have a page with Bootstrap 4 and multiple tabs, each tab with their own datatable provided from a server source via ajax.

If a tab (tab A) starts loading its table and another tab (tab B) is selected before the load completes then the columns won't be aligned when returning to the original tab (tab A).

I am using table.DataTable().columns.adjust() to adjust the columns.
Table width is set to 100%.

I also tried using table.DataTable().columns.adjust().responsive.recalc() with the same results.

If I add draw() as in table.DataTable().columns.adjust().draw() then the columns will align but at the cost of reloading the data from the server.

By putting the adjust() in a sleep timer I noticed that the table wasn't taking the full width of its container and the columns were aligning on the adjust() as if it was.

I found that if I issue the table.DataTable().columns.adjust() twice then everything is aligned; it seems that the first call adjusts the columns and the second call adjusts the table.

This is a rare case (the initial load of a tab isn't allowed to complete while a different tab is selected and then returning to the original tab) so it's not a big issue and the columns.adjust() isn't so expensive that I'm opposed to issuing it twice.

I'm just wondering if it's been seen by anyone else who may know of a simpler fix and I'm posting my case here in case someone else finds it helpful.

Replies

  • allanallan Posts: 61,650Questions: 1Answers: 10,094 Site admin

    If a tab (tab A) starts loading its table and another tab (tab B) is selected before the load completes

    This is the key part here. If you hide the first tab, then the table doesn't have any height / width so it can't resize correctly.

    How are you currently calling the columns.adjust() method? Are you using the method shown here? That should be immune to the issue to describe since the resize will be called every time the tab is activated.

    Allan

  • davedargodavedargo Posts: 10Questions: 2Answers: 0

    I am using a similar method to adjust the columns as described below. However, your suggestion caused me to check another issue. This only happens when the rows of the table are too long and require a child row for the additional columns that didn't fit. If the window is wide enough to accommodate all columns then only a single call to adjust() is necessary.

    I did try the static method and had the same result:

    After the first adjust:

    After the second adjust:

    Here is my adjustment code:

    $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
        if ($(e.target.hash).data('datatable')) {
            $(e.target.hash).data('tablevisible', true);
            $(e.target.hash + 'table').DataTable().columns.adjust();
            $(e.target.hash + 'table').DataTable().columns.adjust();
        }
    });
    
  • kthorngrenkthorngren Posts: 20,269Questions: 26Answers: 4,765

    You are using the responsive extension? If so then you probably will need to use responsive.recalc().

    Kevin

  • allanallan Posts: 61,650Questions: 1Answers: 10,094 Site admin

    Do you have width="100%" or style="width:100%" in your HTML table?

    Allan

  • davedargodavedargo Posts: 10Questions: 2Answers: 0

    Yes, it had been width="100%" and was recently changed to style="width:100%;".

  • davedargodavedargo Posts: 10Questions: 2Answers: 0

    I've done this with and without responsive.recalc() with the same results.

  • allanallan Posts: 61,650Questions: 1Answers: 10,094 Site admin

    I'd need a link to a test case showing the issue in that case I'm afraid.

    Allan

  • davedargodavedargo Posts: 10Questions: 2Answers: 0

    A test case is located here: https://jsfiddle.net/davedargo/rs3yw6d8/2/

    Hopefully, it's just something I've set wrong otherwise the test case may be helpful in determining the cause. I currently just issue two adjustments, though and all is well.

    I've set it up so that the datatable is loaded in Tab 1 but Tab 2 is set as the active display. Selecting Tab 1 will initiate:

    $('#tab1table').DataTable().columns.adjust().responsive.recalc();

    It will then issue a second adjust() after two seconds via a setInterval function. I've included that code below. With the two-second delay you should notice that the first adjustment doesn't completely adjust the window but the second adjustment does complete it. I've included the responsive.recalc() as suggested and the table width is set to 100% via style="width: 100%;".

    $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
      if (e.target.hash === '#tab1') {
        console.log('first table adjustment');
        $('#tab1table').DataTable().columns.adjust().responsive.recalc();
    
        secondAdjustment = setInterval(function () {
          console.log('second table adjustment');
           $('#tab1table').DataTable().columns.adjust().responsive.recalc();
              clearInterval(secondAdjustment);
           }, 2000);
         }
    });
    
  • allanallan Posts: 61,650Questions: 1Answers: 10,094 Site admin

    It certainly looks like Responsive is the code at fault here. Without Responsive it works as expected.

    I'm afraid I don't have an immediate answer for this, but I've filed a bug for this to be looked at before the next release of Responsive.

    Thanks,
    Allan

  • allanallan Posts: 61,650Questions: 1Answers: 10,094 Site admin

    I've just been working with the JSFiddle to try and figure this out - basically what is happening is a result of the scrolling being enabled on the host table. If you do columns.adjust() first the recalc the Responsive display, the hidden elements for the scrolling body are not hidden. They are only hidden on a table scrolling redraw - which we want to avoid here. They are what are causing the alignment issue.

    The answer, in the short term, is to use responsive.recalc() before columns.adjust() - i.e.:

    $('#tab1table').DataTable()
      .responsive.recalc()
      .columns.adjust();
    

    https://jsfiddle.net/5uc71gmv/

    Its a bit redundant, but because DataTables doesn't trigger a pre-column-sizing event, its about as good as we've got at the moment. I could add that event into DataTables core, but with DT2 I want to revisit the whole automatic sizing and adjustment, so with this workaround for the short term, I'll instead move the focus of this issue to v2.

    Allan

This discussion has been closed.