Render is being called, but data in the table is not updated
Render is being called, but data in the table is not updated
Link to test case:
http://live.datatables.net/vinezuga/1/edit?html,js,console,output
Debugger code (debug.datatables.net):
Upload complete - ijohix
Error messages shown:
none
Description of problem:
I'm attempting to update one cell in each row to a value calculated from an external input ('radius' input field) and the value from another cell on the same row. This is a simple version of what I'm trying to do IRL, just to demonstrate the issue.
The render function for the calculated cell is being called, but the data in the table is not updated.
As a result of this testing I also discovered that render is being called multiple times for each row during initialization.
I have 3 rows in the table with one 'data' value per row. The values are 5, 1, -3. As you can see from the console output below, datatables is looping through the renderer twice during initialization.
Once I update my external field (radius) to a valid value, render is called again for each row and the results are calculated correctly (simply add the radius to the 'value' from the row: 5+1=6, 1+1=2, -3+1=-2). However, those values never show in the table. It just shows the original value returned by the first call to render ('??') for each row.
Here's the debug output to the console:
test.html:32 RENDER: Invalid radius; value=5
test.html:32 RENDER: Invalid radius; value=1
test.html:32 RENDER: Invalid radius; value=-3
test.html:32 RENDER: Invalid radius; value=5
test.html:32 RENDER: Invalid radius; value=1
test.html:32 RENDER: Invalid radius; value=-3
test.html:50 Updated radius to 1
test.html:38 RENDER: Updated proximity to 6
test.html:38 RENDER: Updated proximity to 2
test.html:38 RENDER: Updated proximity to -2
Questions
1. Why am I getting double calls to render during initialization?
2. Why aren't the cell values updated with the newly calculated values?
3. How am I supposed to do this so the values are updated as the external input (radius field value) changes?
4. If render is being called, why is it not using / displaying the result?
5. If it isn't going to use the result, why is it calling render more than once (performance issue)?
This question has accepted answers - jump to:
Answers
The second parameter to the render function is the type - so the function will be called several times to get the cell's value for different types. When the table is initialised, it needs to now what to display and the type of the data, so that's why you see two. You will then see a couple more when you first order and search.
columns.render
is only called when the table is initialised. If you want the values to change afterwards, consider using the callbackrowCallback
, or change the data withcell().data()
The other questions have been answered above. Hope that helps!
Colin
Thanks for the test case!
This is due to Orthogonal data.
columns.render
is called to setup the cell for various operations like setting the sorting and searching values, type detection and the display value. So you are seeing the type detection and the display operations, see the updated test case:http://live.datatables.net/vinezuga/2/edit
You aren't changing any Datatables data by using an API like
cells().data
orrow().data()
. I suspect that whencolumns.render
is run Datatables isn't updating the table display due to no changes in the data. You can force the data to be invalidated by usingcells().invalidate()
which will cause Datatables to update the table display. I added this to your test case.Kevin
Colin & Kevin,
Thank you for the info! Very helpful.
I suggest a new example case be added that demonstrates this feature and also explains the interaction of the render function more clearly. It might save future users some frustration.
Thanks again for your help!!!
I guess I'm still a little confused about the call for type "display". Without the call to invalidate(), I still get calls to render for type "display" but the values returned are not actually "displayed," nor are they used for searching.
I know how to solve the original problem using invalidate() (thanks Kevin), but I still don't understand exactly how the render callbacks are being used. If my render callback were making ajax calls or other "long" or "expensive" operations, it seems like they are being "wasted" by redundant calls to render that aren't actually used.
What am I missing here?
Example: http://live.datatables.net/vinezuga/4/
Here I've commented out the invalidate() call and slightly changed the console output to be a bit more clear & compact.
Note that I get two passes with type "display" during initialization (display - type - display). And I get another call with type "display" each time I call table.draw(). But the data isn't actually updated (because I removed the invalidate() call). What's the purpose of these extra type=='display' calls if the data isn't displayed?
Again, thank you both (Colin & Kevin) for your solution to my problem.
That is not the intention nor recommended to execute ajax requests or other time consuming operations. This is to all the table to be rendered quickly. These functions should be performed in the background then the Datatable redrawn with the updated data/information.
Since you aren't updating the Datatables data cache, which is a separate data structure from the HTML table, you need to use
table.cells(null, 0).invalidate();
to have Datatables refresh column 0.I updated your example a bit to demonstrate how updating the Datatables data will update the table display with
columns.render
. Updated column 0 to define a the following property:http://live.datatables.net/vinezuga/5/edit
Since the property is not part of the source data we use
defaultContent
to display a blank cell if the property is not found.In the
keyup
event I added arows().every()
loop to update theproximity
property with the radius. This updates the Datatables data cache and columns.render will update the table display.You likely wouldn't use this example in your solution. I just created it to help demonstrate what we are trying to describe.
Kevin
Excellent! Thank you so much Kevin for your description, information, and code example.