Help on correct usage DataTable and html updated data
Help on correct usage DataTable and html updated data
I have a Rails 7 based application base on Turbo. I also have table with a checkbox (in a form) for each row to apply discount on the item represented by that row. The checkbox triggers a turbo stream update of the html.
As I read the FAQ i have to do a row.invalidate() when updating the html behind DataTable. I'm fully aware of the performance hit here, Im for now willing to just accept that.
I have made a callback that runs on given events, it is being called just fine and looks like this:
dt_invalidate(event){
//console.log(this.tableIdValue) shows the correct table id.
var table = document.getElementById(this.tableIdValue)
//console.log(table) Shows that I got the correct table
//console.log(window.jQuery().jquery) shows my jQuery version to be 3.6
var dt = window.jQuery("#" + this.tableIdValue).DataTable()
dt.rows().every(function (rowIdx, tableLoop, rowLoop) {
//console.log(rowIdx) prints index 0-13 matches number of rows = 14 and debugger Bookmarklet information.
this.invalidate("dom"); // invalidate the data DataTables has cached for this row
});
//$(window).trigger('resize');
//window.dispatchEvent(new Event('resize'));
//dt.columns.adjust().draw();
}
My issue is that it does not really seem to work as expected. I certainly dont think that it is problem with DataTables but rather with my understanding of what I can do with it and how.
What I experience is that data is correctly is shown in the browser when i click on the checkbox and the server roundtrip complets. I can click several of them and it all works great. I check this by "View Source" to get the actual HTML.
If I choose to reorder a column then the checkbox state is the same but values are now back to what is was when the page loaded. I check this by "View Source" to get the actual HTML which is the correct value send by server and by comparing to the developer console elements tab which hold the now incorrect initial values. This is still causing me some head scratching why these are not the same. I thought that DataTables did not use the DOM.
If i hit f5 for reload all data comes back correctly as it is persisted for each roundtrip.
I have then been considering if the invalidation is not sufficient alone. Maybe i need to "redraw" or at least "reload" the html back into DataTables. I have tried each of the following:
$(window).trigger('resize');
window.dispatchEvent(new Event('resize'));
dt.columns.adjust().draw();
and each lead to same problem as before but the with twist that when i click row number 2 then row number 1 flips back to the cached value.
I hope there this some detail of the documentation that i missed that either just tells me to stop my madness or whatever it is that i need to do.
Any hints and help is much appreciated.
Thanks
Jens
This question has accepted answers - jump to:
Answers
Hi Jens,
Can you show me how you are updating the HTML please? Or even better, a provide a link to a page showing the issue?
Allan
Datatables uses a data cache to store the table data and places in the DOM only those rows displayed on the page. As it sounds like you understand from the FAQ Datatables knows nothing about table updates made directly in the DOM and to use some thing like
row().invalidate()
to refresh the Datatables cache.Hmm, I'm not familiar with Rails 7 nor how the
turbo stream update of the html.
works but it sounds like the actual DOM might not be updated?See this simple example:
http://live.datatables.net/ketiguwi/1/edit
Click the Update Ashton button and the Position will change to
Updated
. Search forUpdated
and you will see its not found. Click the Invalidate button then try the same search to see it working.You can use
dt.rows().invalidate().draw()
instead of the below loop if you wish to invalidate all rows.Or if you know the row or rows to update you could supply them as a
row-selector
.Is it possible to provide a link to your page or a test case replicating the issue so we can take a look?
https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case
Kevin
Thanks for the reply Kevin.
Rails Turbo is at it basis a DOM mutator that sends HTML over the wire and thus avoids page tear downs(and most likely many other things I'm not fully aware of, im by no means an expert on the subject:) )
But you raise a valid question:
Do I actually see the DOM update? I will start double checking that. Naturally I'm already asking myself why I did what I did for checking the updates in browser.
I will also have go through the examples and try the
dt.rows().invalidate().draw()
or the row-selector type. Both should be doable.If nothing of that pans out, I will see i can create a short example or free that application page from the application security context in an easy way.
Last resort is to use json and write some more JS and use the Api of DataTables.
Whatever happens, I'll post an update here.
Again, thanks for sharing your thoughts.
Jens
Hi Jens,
It depends a little bit on how the DOM mutation is working if DataTables would even see it. DataTables retains a link to the original
tr
andtd
elements. So if the mutation replaces either of those, and not just the child nodes of thetd
, DataTables would never see it.Allan
Hi Allan
I think that you have just struck my core issue.
I replace the entire
<tr>
and thus DataTables never see it. I noticed this due to some DataTables Class names (even/odd etc) got removed while I was following up on Kevins question from yesterday. This was my follow up point today if that was causing me issues.Just be sure that understand your comment on children correct:
<td>my_value</td>
has no children and if replace the entire
<td>
i end up in the same situation.If i do something like:
<td><span id="my_id">my_value<span></td>
and replace
<span id="my_id">my_value<span>
with<span id="my_id">my_other_value<span>
then from a DataTables point of view it should be workable ?Thanks for the answer.
Jens
Hi
Kevin and Allan, thanks for your help. I would not have come to this conclusion without it.
For anyone else that comes by here with a similar problem:
I have implemented the child solution with span as outlined above. That is, I wrapped the value in
<span id="spanid">
.Then in a stimulus controller that wraps DataTable I have:
and
The span is simply just handled by turbo_stream on the rails side:
Thanks
Jens
Hi Jens,
Great to hear you found a solution.
Just to clarify:
It actually does. It has a text node child (which contains
my_value
in this case). It doesn't have any elements as children though, which might be causing the confusion there.Ideally the DOM mutator would be able to work with the text nodes mitigating the need for loads of ids, but depending on how it works, that might or might not be possible.
Allan