Render is being called, but data in the table is not updated

Render is being called, but data in the table is not updated

james1james1 Posts: 4Questions: 1Answers: 0
edited February 2021 in Free community support

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

  • colincolin Posts: 15,237Questions: 1Answers: 2,599
    Answer ✓
    1. Why am I getting double calls to render during initialization?

    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.

    1. Why aren't the cell values updated with the newly calculated values?

    columns.render is only called when the table is initialised. If you want the values to change afterwards, consider using the callback rowCallback, or change the data with cell().data()

    The other questions have been answered above. Hope that helps!

    Colin

  • kthorngrenkthorngren Posts: 21,174Questions: 26Answers: 4,923
    Answer ✓

    Thanks for the test case!

    Why am I getting double calls to render during initialization?

    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

    Why aren't the cell values updated with the newly calculated values?

    You aren't changing any Datatables data by using an API like cells().data or row().data(). I suspect that when columns.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 using cells().invalidate() which will cause Datatables to update the table display. I added this to your test case.

    Kevin

  • james1james1 Posts: 4Questions: 1Answers: 0

    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!!!

  • james1james1 Posts: 4Questions: 1Answers: 0

    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.

  • kthorngrenkthorngren Posts: 21,174Questions: 26Answers: 4,923
    Answer ✓

    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.

    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.

    What am I missing here?

    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:

            data:           'proximity',
            defaultContent: '',
    

    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 a rows().every() loop to update the proximity 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

  • james1james1 Posts: 4Questions: 1Answers: 0

    Excellent! Thank you so much Kevin for your description, information, and code example.

This discussion has been closed.