rowCallback breaks sorting

rowCallback breaks sorting

ztgadminztgadmin Posts: 11Questions: 4Answers: 1

Why when rowCallback is used here https://datatables.net/reference/option/rowCallback to update a cell contents the sorting nolonger works. Is there another way to update a cell contents after the rows have been rendered and not break sorting?

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 61,848Questions: 1Answers: 10,134 Site admin

    Hi,

    Thanks for your question. You can't use the rowCallback option to modify the data in the DOM and have DataTables use that modified data for the sorting I'm afraid. There are basically two reasons for this:

    • Reading information from the DOM is very slow. For that reason DataTables keeps a cache of the information that will be used for sorting. As such, if the data for sorting needs to be changed, the cache needs to be invalidated.
    • rowCallack is only called when the row is drawn, but the sorting information might be needed before that (for example when deferRender is enabled).

    The solution to the issue is to not use rowCallback to change the data in the cell - rather a data renderer should be used.

    Perhaps you could give me some more details of what your use case is, and I'll try to fill in the gaps for how to use a renderer to achieve it.

    Regards,
    Allan

  • ztgadminztgadmin Posts: 11Questions: 4Answers: 1

    So, part of my issue is that I need to still fetch the data I want to add to the other cells and have not been able to use render to fetch the data then return it.

    So, I'm making 2 server calls. Call 1 fetches the first 6 columns of data then adds them to the table using the below code. Then once the data is rendered I tried to make another server call to obtain the data for columns 7 to 27 with the below code

    Populate columns 7 to 27
    "columnDefs": [
    {
    'targets': 0
    ,'render': function (data, type, row) {
    //Make server call on once data is returned populate return value
    }
    }

    Populate columns 0 to 6
    tblObj.rows.add(JSON.parse(newJSONdata)).order( [[ 0, 'asc' ]] ).draw(false);

  • ztgadminztgadmin Posts: 11Questions: 4Answers: 1
    Answer ✓

    I was able to figure out what I needed to do. This ticket can be closed.

  • allanallan Posts: 61,848Questions: 1Answers: 10,134 Site admin

    Hi,

    Great to hear! I'll provide my own thoughts on this if that's okay (without impacting your support credits of course).

    You really don't want to make an Ajax call in the render function. It is meant to be synchronous and can be called many times.

    So one option is to use the createdRow callback. Then that is triggered, have that make your Ajax call to get the extra data for the row, and then use row().data() to update the row's data with the new information (this making it available for sorting, filtering, etc).

    The only disadvantage to that is that it would create an Ajax request for every row. Probably okay for low volume / internal sites, but you would DDoS your own server if it was a busier site!

    For that you would need to use drawCallback and determine which rows from the existing page don't have the extra data available, then make a single call to get that data.

    The downside to this approach as a whole is that you can't sort of filter data that hasn't been fetched yet, making things a little more tricky.

    How many rows are in your table? Are there enough that including all of the data up front would seriously impact performance?

    Allan

  • ztgadminztgadmin Posts: 11Questions: 4Answers: 1

    Hi Allan,

    Sorry for not providing details in what I used. I ended up using the createdRow option then the row().data() API to accomplish my task. Thanks

    The number of rows in the table are around 250. The reason I decided to know load all of the data up front was because to obtain the data for the first 7 columns doesn't take much processing time. However, to obtain the data for the rest of the columns can take some time to process. So, instead of waiting for all of the data to load, I wanted to give the perception that the data was loaded faster than it really is by showing the rows and having columns 0 thru 7 populated while the user will see the reaming columns populate with data.

This discussion has been closed.