Code broken after updating to latest libs
Code broken after updating to latest libs
DESCRIPTION: In an older version of the libs, I had code which would perform Archive, Trash Bin, and Restore operations. In DT terms, I'd be on a table of (10) rows, perform one of the operations, and essentially delete the selected rows from the table and redraw it. This has stopped working since I updated so obviously something is wrong in my call that the new libs do not like. Hopefully the below code will give you enough to point me in the right direction.
Before Code (this worked perfectly)
Adding Index to column (2) of the table:
// Populate the # column with the index method.
tableConfig.on( 'order.dt search.dt', function () {
tableConfig.column(2, {search:'applied', order:'applied'}).nodes().each( function (cell, i) {
cell.innerHTML = i+1;
tableConfig.cell(cell).invalidate('dom');
});
}).draw(resetPage);
Archiving Operation (removing selected rows from the current table)
archiveTableToUpdate.rows('.selected').every( function(rowIdx, tableLoop, rowLoop) {
// Remove the remaining rows as the API successfully deleted them from the DB.
archiveTableToUpdate.row('.selected').remove().draw(false);
});
_Current Code _ (taken from the example on the datatables.net page)
Still adding Index to column (2)
tableConfig.on('order.dt search.dt', function() {
let rowNumber = 1;
let rowIdx = tableConfig.row(this).index();
tableConfig
.cells(rowIdx, 2, {search: 'applied', order: 'applied'})
.every(function(cell) {
this.data(rowNumber++);
});
}).draw(resetPage);
ERROR
TypeError: null is not an object (evaluating 't.aoData[n]._aData') - datatables.min.js:11200:178
NOTE: If I comment out both versions of the index code, everything works perfectly. So I'm not processing something properly when the row is removed and the Index needs to be redrawn but I cannot figure out where.
In the old row.index code I am performing an .invalidate operation which I think I need. However, I've tried placing this in various places with no success. Also, I am no longer using "dom" to draw things as I switched over to the "layout" functionality which I believe I'm supposed to use. But this may also be the issue as the dom may not be available--maybe I need a little bit of the dom, but it's not there now and if I comment out row.index() code everything works just fine.
Any help is appreciated. I hope the provided code is enough as my app is large now and not sure pasting all of it is beneficial.
Edited by Kevin: Syntax highlighting. Details on how to highlight code using markdown can be found in this guide
Replies
This code still seems to work in this test case running Datatables 2.1.5:
https://live.datatables.net/japonabi/1/edit
Note I changed
.draw(resetPage)
to.draw()
as I'm not sure whatresetPage
is.There are a couple issues here. For the
cells()
row-selector
you should passnull
, which means all rows, as the first parameter. Looks like you are trying to pass in a row index. See the example.I did the same with
resetPage
. Test case with this updated code:https://live.datatables.net/haqiqese/1/edit
This loop doesn't seem right:
It seems it might work but its lopping through one or more rows using
.rows('.selected').every()
. In the loop its using.row('.selected').remove()
which will return only the first row found. You could just use this:A best practice option, when using the Select extension, is to use the
selector-modifier
of{ selected: true }
, like this:If you still need help please provide a link to a test case replicating the issues so we can help debug.
https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case
Kevin
@kthorngren Roger that and as always, THANK YOU for the quick response! I'll make the modifications and review your examples for me. Since I am updating to the latest libs, I am taking the time to also clean up any of my bad code and align things with the best practices. Stay tuned
/@kthorngren ok, I'm going to try to mock this up in a test case for you. But here's what I have discovered.
On initial load of my tables, both index code snippets work just fine. But it's on a redraw where it is breaking. For example,
Row 1
Row 2
Row 3
I remove one of the rows (doesn't matter which one) and it removes the row successfully, but breaks on my .draw() on my archiveTableToUpdate.rows( (selected: true ).remove().draw().
If I remove the .draw() the code continues successfully--of course it doesn't update the table in my view. Or if I comment out the code that provides the indexes and leave the .draw() on, it successfully completes and redraws the table.
In summary, if I use the index code it seems like I need to invalidate the indexes somehow because again, if I don't use indexes everything works just fine. Anyway, stay tuned as I try to get this mocked up and hopefully I can break it so you can see what I mean.
This clue helped. It does seem there is a difference in the way Datatables 1.x and 2.x works when using
row().remove()
.Here are simple test cases that shows the behavior difference using
column().nodes()
in theorder
,search
anddraw
in the 1.x and 2.x. Open the browser's console to see the results of clicking theDelete Ashton
button.1.13.11 works:
https://live.datatables.net/buhayopa/1/edit
2.1.5 results in this error:
https://live.datatables.net/japonabi/2/edit
2.1.5 has the same error with
column().data()
.@allan will need to take a look.
Kevin
Awesome, glad I am not crazy I will review what you've provided and wait to hear back from @allan. Worse case for me at the moment is I just remove that column and continue updating the my code to work with the latest libs in other areas.
The issue has nothing to do with the index column. My example simply use
row().remove()
then outputs the following in each event:There is no code manipulating the index column. It seems something isn't properly updated in the Datatables cache causing the error when using
column.nodes()
in theorder
event handler. The 2.1.5 test case now works after commenting out the console.log statement in theorder
event:https://live.datatables.net/japonabi/3/edit
Kevin
@kthorngren my apologies, I didn't mean to imply that the index was still the issue. Only that I can disable it and everything works for me. So if I need to move on, I can as having the indexes is just a nice-to-have in my app.
I looked at your example, and col 2 doesn't have any data in it. I have duplicated this in my code and it works. For me, as long as col 2 doesn't display a value it works. It's only when an actual value is present/displayed that it breaks.
But you've given me quite a bit to noodle on and as a "very" old school developer, I shy away from being spoon fed. So, I'm going to see what I can come up with based on your feedback.
One idea I had is to populate col 2 at the time I generate the table data. Currently, I generate the table data away from the index. I'll report back after I've done some more testing on my end. I think this is a simple issue, but I just can't put my finger on it just yet.
The problem is not that you have indexes or display a value in column 2. The problem occurs when using
column().nodes()
in theorder
event. I believe this is a bug in Datatables and if it is then Allan will fix it as it could affect other solutions.You could move the code into either
initComplete
orinit
so it runs only once. The index value won't change on sorting or searching.Another option is to place the code in the
draw
event. However it will execute anytime there is a draw event including paging. This will allow the index to update and start with 1 at the top of the firs page. However it will run more often even when its not needed to change the index.The option you choose is based on your requirements.
Kevin
My apologies, just saw the update you made on my initial comment for code highlighting. Will use that going forward.
I know you aren't arguing but there seems to be a bug within Datatables that when the
order
event is fired the removed row hasn't been updated. I updated my test case with this for each event:https://live.datatables.net/japonabi/5/edit
On table load the output shows this:
After deleting a row the output shows this;
The table should have 4 rows and after deleting but the
order
event still sees 5 rows. However the search and draw events see the remaining 4. As I said before there appears to be a bug in Datatables, with the order of events, where theorder
event is fired before the row is removed.This is something @allan will need to look at.
Kevin
Understood. But I also tried the newer code example found here that does not use columns().node().
So, to get the indexing I have tried the following:
NEW CODE
ERROR
Unhandled Promise Rejection: TypeError: null is not an object (evaluating 't.aoData[n]._aData') --- datatables.min.js:34:66928
OLD CODE
ERROR
Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'e[t[o]][n]') --- datatables.min.js:34:873
Ignoring the "resetPage" variable as it doesn't matter for this troubleshooting.
Just of r fun remove the
order.dt
fromtableConfig.on( 'order.dt search.dt', function () {
. What happens?Kevin
BINGO!!! Removing order.dt in both code snippets resulted in success. @kthorngren I cannot thank you enough for helping through this.
Let me know if this should be the final implementation or if something needs to be fixed in the lib and I should continue to use order.dt. For now, I can move forward with my updating.
UPDATE: I just saw your previous reply regarding the order.dt being called too soon. So I will keep an eye out for the fix and update my code accordingly. But at least I can move forward now.
TL;DR for @allan
See this test case:
https://live.datatables.net/japonabi/5/edit
The table starts with 5 rows. Using
row().remove()
followed bydraw()
causes theorder
event to fire. Thecount()
ofcells()
insideorder
still shows 5 but should be 4. It seemsrow().remove()
isn't fully removing the row which looks like its cleaned up by the ordering process. Usingcolumn().nodes()
orcolumn().data()
inorder
causes exception errors.Kevin
@kthorngren not sure if this is related but in the old DT version I was using, the index column did not update when the other columns were sorted. It stayed 1, 2, 3, ... when say, the Project Name column was sorted. However, now it is updating when the columns are sorting so 1, 2, 3, ... becomes 10, 9, 8, ...
Other than the order.dt you had me take out, I have not changed anything else. Any ideas? Thx.
PS: I did search for this but even the Column Index example the indexes are not changing when the table is sorted.
UPDATE: Never mind my question, it is because the order.dt has been removed. So, I'll just plan on waiting on Allan and the fix to rollout.
This one gets right into the depths of DataTables . Thanks for flagging this up and also to Kevin for your test cases and analysis.
tl;dr: fix committed here, and it will be in the release later today.
One of the big changes in DataTables 2 was to switch the internal data store to be a sparse array. So when you delete row index
2
, another row doesn't suddenly become row index 2, rather index 2 is nownull
and can't be replaced (server-side processing is an exception). This was done as API instances will keep their index reference, even after a row is deleted, so you might suddenly start operating on a different row (it was unusual, but it wasn't a good way to handle things).This means that if we try to access information about row index 2, it is going to fail with an error message about being unable to access an array index, like you are seeing.
This is where it gets grizzly - when a row is deleted, I update the "master" index, but not the "draw" index arrays (due to this fix). The "draw" index array is updated on the next draw - so there is a period of time after a
row().remove()
call, that if you query the drawn table, it will still refer to the deleted row. If you remove the{search:'applied', order:'applied'}
it works fine since it uses the "master" index, but with that it uses the "draw" index.The
order
event happens before the "draw" index is updated - thus the error!I can't update the draw index on delete, per the previous fix, but what I have done is added a little extra check to make sure that the data being referenced is not
null
.Phew - that woke me up on a Friday morning!
Allan
Very nice, thanks for the detailed explanation.
Kevin
@allan thank you for the detailed explanation and the fix! I know I say this every time I post, but you guys truly ROCK!!! And I am so happy I found DT years ago. My apps have been well-received because of the functionality DT provides. Thanks a million!!!!!
@allan just saw that 2.1.6 was available, so I updated to point to it (I was on 2.1.4). Anyway, I am getting the same error message when I add "order.dt" back into my code.
Works fine without "order.dt", but then the index column becomes a part of the sort, which I do not want.
Just let me know if I am missing something. As I told @kthorngren, I can simply remove my index column permanently and move on. I'm not sure how much my customers care about having an index column anyway--I like it myself.
There still seems to be some issues to work out. This test case uses your first example with
column().nodes()
. The exception error doesn't occur but the indexes aren't updated when the table is sorted by another column:https://live.datatables.net/japonabi/11/edit
Order by the Position column but the output of the Name column is in the previous order:
Delete Ashton and the indexes are updated properly.
Using the
cells().every()
solution in this test case results in this error:https://live.datatables.net/lufisuzo/1/edit
Note the output of the number of cells remains
5
after deleting Ashton.@allan will need to look further.
Kevin
Perhaps
.every()
should be checking that the row it is given hasn't been deleted, however, that wouldn't resolve it for multi-page tables since{search: 'applied', order: 'applied'}
reads from the display index and thus would be wrong.If you need to update data to create something like an index (which is what I presume is happening here), do it in
draw
rather than the order / search events.I'll need to have a deeper think on the architecture of this - perhaps those events need to be delayed.
Allan
@allan sorry for the delay in response. I will see if I can move the index routines into the .draw() function and if not, I can simply remove that column as it is the only thing that breaks after since I've updated to all of the latest libs. I also think I can simply create my own index when I build the other columns in the table. That way, it doesn't refresh the indexes until the user refreshes the entire table.
For example, I have rows 1, 2, 3. I delete row 2. The .draw() would update so the table shows 1 and 3. However, if the user clicks my table refresh button, it would reset the index so it become 1 and 2. Not sure if that is viable to the end users, but it doesn't really bothering me at all. Plus, it might be ok to know what rows I deleted (in this case row 2) before refreshing the table.
Anyway, I don't think this is a show stopper and as I've stated I can always remove the index column from the table and move on. Thanks for looking into this for me and I'll keep an eye out just in case you resolve this issue in a more permanent way.
Create a function to build the indexes. Use
initComplete
to call the function to generate the indexes on table initialization. Call the function to refresh the indexes if desired.Kevin
Roger that @kthorngren I forgot you recommended that in an earlier post. Thanks for the help and guidance, I should be able to resolve this issue today and move on. I updated to all the new libs b/c I want to start using the Editor libs so I wanted to be sure all lib versions were properly aligned.
@allan and @kthorngren my sincere apologies as I totally missed this line in Allan's original post regarding the fix he applied:
" If you remove the {search:'applied', order:'applied'} it works fine since it uses the "master" index, but with that it uses the "draw" index."
As I was rereading this thread today, I saw it, removed it and everything works just fine now with the rest of my code "as is". We can close this bad-boy out now.
Thank you for all the guidance and patience on this one!
No worries - thanks for letting us know. Good to hear you have a solution and thanks for brining this up. It's been an interesting topic and one I need to think further about.
Allan