dataTable.row.add(json) and dataTable.ajax.reload()
dataTable.row.add(json) and dataTable.ajax.reload()
dma_k
Posts: 18Questions: 3Answers: 0
Dear community,
I my scenario I have dataTable which is bound to some AJAX source. And it happens that during the execution of dataTable.ajax.reload()
the function dataTable.row.add(json)
is called. As the result:
aoData
now contains results from server (N rows) plus one row added byrow.add()
.- This additional row (N+1) is not displayed on the screen (which caused real headache in catching the problem).
I think that DataTables are not behaving correctly in this case. If callback(json)
is invoked, add data rows should be removed before new are added.
Code in __reload()
:
_fnClearTable( settings );
var data = _fnAjaxDataSrc( settings, json );
for ( var i=0, ien=data.length ; i<ien ; i++ ) {
_fnAddData( settings, data[i] );
}
Suggested:
var data = _fnAjaxDataSrc( settings, json );
_fnClearTable( settings );
for ( var i=0, ien=data.length ; i<ien ; i++ ) {
_fnAddData( settings, data[i] );
}
This discussion has been closed.
Answers
The
_fnAjaxDataSrc
function should be extremely fast - unless there is an override inajax.dataSrc
the action is not asynchronous, so there should be virtually no difference between the two code suggestions above.Have you used
ajax.dataSrc
?I don't see a problem making the change above, I'm just concerned it won't solve the issue. Are you able to link me to a page showing the problem?
Allan
M-m-m. Why? I pass the following option to DataTables:
Request to backend may take a while. Even if backend is "extremely fast" and replies in say 50ms, this time is enough to call
dataTable.row.add(json)
and make a damage.First of all, the problem cannot be revealed just by showing you a particular page with some request. The problem was revealed under testing of the application under high load, basically, creating dozens of parallel requests to JavaScript application. And it turned out that in majority of cases the whole test suit passed OK, but in some cases it failed. The rate was 1/30 (1 failed vs 30 successful). These kind of problems are difficult to catch, and it took me literally 2 weeks of observations and experiments to find out the problem. Partially the problem is in application (it shouldn't allow table update while it is reloaded), but the component is also misbehaving, as its model and view could be made inconsistent. Namely: two identical records are present in the model, only one row is displayed. Even if I would be able to give you such URL or screenshot, you won't get much as visually it looks OK. The only way to debug the problem is verbose JavaScript logging (that include AXAJ requests), putting high load and having a lot of patience.
Because all it does is check the settings to see what property should be used and simply return that property. It doesn't make the Ajax call itself.
Sure - but that has nothing to do with the
_fnAjaxDataSrc
function. It is synchronous and only useful once the Ajax call has completed.The internal
_fnBuildAjax
function is what makes the Ajax request, and the function passed to it is what is run after the Ajax load has completed.As I say, I don't have a problem moving the call around - I just don't think it will solve the issue. It might reduce the hit rate from 1 in 30 to 1 in 60, but it is hard to say.
Allan
Yes, you're right.
_fnAjaxDataSrc
is not making AJAX call. I was wrong. There is something different that causing the problem. Perhaps you have an idea? Could it be the code in_fnAddData
?My best guess is that you are running into a timing issue. As I say the change in order of the code you made tipped the scales slightly more in your favour so you just made is less likely to happen.
I think I need a better understanding of what is happening - and I'll probably need to try and set aside a couple of hours sometime to try and reproduce the problem sometime (although I can't guarantee when that would be at the moment).
You said:
Does the information element below the table show the correct row count?
Does calling
draw()
solve the issue? Are you callingdraw()
after yourrow.add()
call (as the documentation notes this is required)?Allan
Yes, I do call
draw()
function, exactly like this:dataTable.row.add(json).draw(false);
When table is corrupted, the number of rows in the model is reported to be 10, but only 9 are displayed. Here comes the screenshot. The row with ID 63371 is present twice in the model, but shown only once. The one added to the end of the model is added by
row.add()
. As sorting is descendant by column ID, there should be two rows.I have also dumped the whole object as JSON. I have removed most columns from screenshot and data values from JSON, so don't pay attention to the fact that number of columns does not match the model.
I have also to make this note: The problem is happening not exactly with
dataTable.ajax.reload()
as this topic subject says, but during initial table creation:but I feel this is equivalent to:
Thanks for the extra information. It is almost equivalent, but not quite. The API methods will do a table clear before adding the data, while the initialisation will not. That might well be the problem. It isn't something I've tried before.
Can you try adding the data using
initComplete
- i.e. after the JSON data has been loaded.Allan
No, you have misunderstood me :) I don't have a specific intention to add one row just after table initialization, and of course
initComplete
will do it job well.Let's assume that there is another polling cycle, that listens on incoming updates from the server:
So this event (table row update) is not under my explicit control. The workaround is that I create a
jQuery.deferred
that puts all updates in a queue to be executed afterdataTable
is completely initialized.If you say the current implementation is correct, then I should see two rows in a table. It should not matter that initialisation does not clear the table. Table should be consistent.
Hi,
Sorry I misunderstood. However, could you put your
startPolling
intoinitComplete
? Or is it not under your control to start the polling?I suspect you might need a queue in the polling start up to make sure that the table is fully initialised before items can be added.
Regarding the current implementation on startup - I'm not sure if the current implementation is correct - it isn't something I've tested before - what happens to rows added while an Ajax load is occurring. I'll need to spend a little bit of time researching what is happening there, but I'm not sure when I'll get a chance to do so, as things are a bit busy atm!
Allan
The poller generally pushes information into other UI elements, not only table. So I cannot put it into
initComplete
. I have applied workaround for the problem, it's more about the DataTable component. Leave it for future.I also have some signs that there is tension between
dataTable.row(rowNode).remove().draw(false);
anddataTable.row(rowNode).data(json).draw(false);
, basically the same table row is deleted and updated simultaneously. The side effect is that row is actually not deleted (stays visible), however I would expect that that the row is removed. I don't have much information concerning this scenario, perhaps will take me few weeks to collect it.Thanks for this - yes I suspect there could be potential for async issues between using the
ajax
methods to get new data and the client-side methods to manipulate the data. The clear table being immediately before the data add for the ajax reload should mitigate most, but with async processing (both from the polling handler and the ajax) there is likely always to be potential for issues, unless some kind of queuing is implemented.As a quick example:
ajax.reload()
The fact that there are two data sources is causing the issue. Possibly DataTables should have an internal queue to handle this - although that would add a fair bit of code weight to the core library I think.
I'll need to have a bit more of a think about this.
Allan