Event when DT is really ready?

Event when DT is really ready?

elstupidelstupid Posts: 12Questions: 2Answers: 0

I was wondering if there's an event which I can hook into when DataTables is really finished loading.

I know we can use initComplete or $table.ready() but those events/functions fire before row rendering has completed.
The draw() event fires many times during rendering which is also not very helpful.

My case:
I load data through AJAX and render rows with some rendering functions. In that row rendering I create buttons on which I want to hook some events. However the buttons are only rendered after initComplete and ready.

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 64,631Questions: 1Answers: 10,686 Site admin

    those events/functions fire before row rendering has completed.

    No - they happen once the table has been drawn in the document. The DOM structure for the table is fully in place with the loaded data.

    Possibly you have some external rendering happening (your last paragraph does indicate that might be the case) - without a test case I'm not sure. Perhaps you can post a link.

    Allan

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086

    Maybe you need delegated events like this example. Not sure though without knowing the issue you are running into. As Allan suggested please provide a link to a test case so we can see what the issue is to help debug.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    Well I just posted my example, which took me some 45 mins to compile. After 1 or 2 edits everything is gone now on this page, really frustrating and at this point I don't feel like doing 45 minutes again :(

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086
    edited June 24

    Possibly the edits hit the spam filter. @allan can look and post it if it's there. Lets wait to see what Allan finds.

    Is it a running test case that you have a link to?

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    No it's not. I can't provide a real life example, it's all behind a corporate login. I have many datatables on many pages, sometimes more than one on a page. That's why I seperated my tables from javascript logic for the most part and only configure the tables through a local js settings object.
    Also, I load data through ajax, for which I can't provide an example through live.datatables.net I think

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086
    edited June 24

    There are Ajax and server side processing templates you can start with here. Possibly you can use one of those and show how you are rendering the buttons and replicate the issue.

    What is the problem you are trying to solve? Is it the issue described in this FAQ?

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0
    edited June 24

    Well I'm one step further now. It seems you're right about the order of events. I put an alert in the row rendered and in the initComplete.
    I get row renders first and after that a initComplete. However, what is rendered is only shown after that, because of the loading message (loadingRecords).

    So it's almost impossible to attach an event there. I'm rendering buttons in my rows, but I can only attach on $(button).on("click") after button is added visibly to the dom.

    I'm looking for an event happening after the loadingRecords message is gone and buttons are attached to the document

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086

    As I mentioned in my first response take a look at the delegated events example. You may want to toggle between jQuery and Vanilla JS code displays at the top of the page. The jQuery delegated events doc provides more info of how this works.

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    OK thnx Kevin, will check out the delegated events, seems that might be useful.

    BTW: you can see the loadingRecords message only spans one column, it may be the same issue as I mentioned here

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086
    edited June 24

    Here is a simple example with two buttons:
    https://live.datatables.net/xijecupo/2741/edit

    One has a jQuery event handler and the other a vanilla js handler, similar to the example I linked to. If you still have difficulties please update my test case with what you are trying.

    BTW: you can see the loadingRecords message only spans one column, it may be the same issue as I mentioned here

    Probably. Allan asked for a test case showing the issue so he can debug. If you can provide access you can PM Allan with details to access your solution.

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0
    edited June 24

    Thanx again, I did some rework and with delegated events it's now working.

    Either way it would be nice to have an event when all is ready and displayed.

    Will try and look into an example for my other problem and updated that post accordingly.

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086

    Datatables only adds to the document those rows displayed on the page. This is explained in the FAQ and example I linked to. initComplete and ready() fire "when all is ready and displayed.on the initial page". You can use things like draw if you need to apply things to the rows when they are added to the document when the display changes.

    Does this make sense?

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    Well, draw() fires multiple times depending on how many records there are. And as you can see in my screenshots, initComplete fires when the loadingRows message is still in the way. What I was looking for is a single event that fires when all rows are attached and displayed in the DOM.

  • allanallan Posts: 64,631Questions: 1Answers: 10,686 Site admin

    I need a link to a test case showing that problem please. As far as I know initComplete fires only after the data has been loaded into the document (that's certainly how I wrote it to behave). See this example.

    draw will trigger once when the "Loading..." message is displayed (if ajax is used) and then again when the data is drawn.

    There is something I'm missing here, based on your description. As I say, I'd need a test case.

    Allan

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086
    edited June 25

    Have you looked at the browser's console for errors?

    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    @allan I kinda replicated the situation of your testcase, where I replaced your console.log with an alert().
    The initComplete clearly fires before the rows are shown, see my example
    This could be intended behavior

    I'm mistaking draw() for the drawCallback(), but draw() happens even before initComplete()

    @kthorngren Already checked, there's no errors in my console

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086
    edited June 25

    Allan can confirm but the alert in initComplete is executing before the browser as updated the display and its blocking the browser from updating the display. I updated your test case to add a very small delay using this:

      initComplete: function () {
        setTimeout(() => {
          alert("init dtDocuments done");
        }, 0);
      }
    

    https://live.datatables.net/wahopaha/4/edit

    I made another change to your test case to use console.log statements without the setTimeout. It outputs the number of rows found in the DOM when initComplete executes using this:

      initComplete: function () {
        var numRows = $('table#dtDocuments tbody tr').length;
        console.log("init dtDocuments done displaying " + numRows + " rows");
      }
    

    https://live.datatables.net/wahopaha/5/edit

    I believe this shows that initComplete behaves as documented:

    It can often be useful to know when your table has fully been initialised, data loaded and drawn, particularly when using an ajax data source.

    IMHO its better to sue console.log when debugging as alerts will block the UI.

    Kevin

  • allanallan Posts: 64,631Questions: 1Answers: 10,686 Site admin

    Allan can confirm but the alert in initComplete is executing before the browser as updated the display

    Exactly that! If you query the document (as my example did) you will see that the document structure is up to date with all of the row data. However, the painting of the page on screen is done in a separate thread of the browser. I don't know the details (modern browsers are a dark art imho ;)) but the basic idea is that it allows multiple DOM updates to occur with a single repaint (the reflow and paint are expensive operations - it is easy to kill performance by forcing the browser to reflow frequently - e.g. reading a height or width property in a loop).

    The browser will wait a short while to see if there are any other updates to paint (grossly over simplified...). Also, as Kevin says alert() is blocking, so it stops all other interaction (including reflow and painting).

    Allan

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    My point with the alert() was to proof the initComplete() happens before the DOM is completely done. This means you can't ever bind an event to elements in a row from that event, because there's a sure chance they don't exist yet.

    So that answers my original question. Yes, DT might be done but the browser may not be done.

    Anyway the delegated events did the trick for me in this case.

  • allanallan Posts: 64,631Questions: 1Answers: 10,686 Site admin
    edited June 26

    The paint isnt done, but as my example showed the DOM is fully up to date and you can bind events to the elements.

    Good to hear delegated events work for you, they are much more efficient for this sort of think anyway!

    Allan

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086
    edited June 26 Answer ✓

    My point with the alert() was to proof the initComplete() happens before the DOM is completely done. This means you can't ever bind an event to elements in a row from that event, because there's a sure chance they don't exist yet.

    That is not entirely true. As Allan said:

    you will see that the document structure is up to date with all of the row data. However, the painting of the page on screen is done in a separate thread of the browser.

    I updated the last test case to show click events can be applied to the rows displayed on the page from inside initComplete.
    https://live.datatables.net/wahopaha/6/edit

    The DOM elements are available and the event handler is applied so you can click on any row on page 1. However Datatables only places the rows displayed on the page in the DOM. If you navigate to page 2 the elements from page 1 are removed from the DOM and the elements from page 2 are added. Since they weren't in the DOM when the event handler was instantiated they don't have click events applied. This swapping of rows placed in the DOM is why delegated events are needed. Go back to page 1 and the click events are still applied.

    HTH,
    Kevin

  • elstupidelstupid Posts: 12Questions: 2Answers: 0

    Must be a timing issue on my end then, because I can't always bind an event to a rendered button.
    Delegated events are the far better solution for my case, so I will mark this as done

  • kthorngrenkthorngren Posts: 22,070Questions: 26Answers: 5,086

    Must be a timing issue on my end then, because I can't always bind an event to a rendered button.

    Maybe it's how or when you are rendering the buttons. If want to to take a further look please post a link to a test case showing the issue.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Otherwise delegated events are the way to go :smile:

    Kevin

Sign In or Register to comment.