How do I update the data in the table without clearing and re-adding the rows

How do I update the data in the table without clearing and re-adding the rows

advscradvscr Posts: 4Questions: 1Answers: 0

Hello all,
I have a table being populated by a subscription to WebSockets. So when the new data comes, I do this:

table.rows().remove();
table.rows.add(data).draw(false);

Is there any way to update the data without removing the existing rows first?
The problem is the behaviour is noticeable when the user selects rows or interacts in any way with the table and some updates come at the same time

thanks for your help

Answers

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736
    edited March 2017

    Your table will need to have a unique column. When you get the data you need to check to see if it exists in the table and update if so or add if not.

    Here is an example that I've used in the past:

    var indexes = table.rows().eq( 0 ).filter( function (rowIdx) {   // get the row index matching the unique value
        return table.cell( rowIdx, 0 ).data() === <unique value> ? true : false;
    } );
      if (indexes.length > 0) {
        table.row(indexes).data( <data to update> );
      } else {
        table.row.add( <data to add> )
        .draw(false);
      }
    

    The <unique value> is from the websocket service. This script looks in column 0 for the unique value return table.cell( rowIdx, 0 ).data().

    Kevin

  • advscradvscr Posts: 4Questions: 1Answers: 0

    Hi Kevin and thanks for the reply.
    my table has a unique value, also defined as rowId, but that value is not displayed in any column. So I would have to get the name of rowId somehow.

    This is also because every time I get all the data, so I will need to check for each row, and compare the rowId to decide if the row is already in the table or not.

    something like this:

    for x in data {
        var row = table.row(x[table.rowId]);
        if (row != null) row.data(x);
        else table.rows.add(x);
    }
    table.draw(false);
    

    but table.rowId doesn't seem to exist. Is there anything like the above?

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    It is possible to iterate all the rows using rows().every(). You can access any of your data elements whether in a column or not. Using the rows().every() example you might be able to get the rowId with data["rowId"]. Not sure how your data is structured though.

    Kevin

  • kthorngrenkthorngren Posts: 20,141Questions: 26Answers: 4,736

    It is possible to iterate all the rows using rows().every(). You can access any of your data elements whether in a column or not. Using the rows().every() example you might be able to get the rowId with data["rowId"]. Not sure how your data is structured though.

    Kevin

  • advscradvscr Posts: 4Questions: 1Answers: 0

    my code is quite generic and handles situations where the key might have different names. So, instead of hardcoding it like this: data["key"]
    I want to get the name of the id column at runtime: data[table.rowId]
    Is this possible? couldn't find anything in the docs.

  • allanallan Posts: 61,439Questions: 1Answers: 10,053 Site admin

    Using the row-selector as a function is the way I would suggest doing this. You can have it search the data for the rows to select the row matching the id you want (as you say, if you have that value in a variable, just use the variable for the matching).

    Save the return into a variable then you can do any() to see if there was an existing row with that ID. If so, update it. If not, add it.

    Allan

  • advscradvscr Posts: 4Questions: 1Answers: 0
    edited May 2017

    it's been a while but I finally got around to working a bit on this issue. This is the code I ended up with:

                var key = table.context[0].rowId,
                    dataKeys = message.data.map(function(item) { return item[key]; });
    
                // remove obsolete rows
                table.rows(function (idx, data) { return $.inArray(data[key], dataKeys) === -1; }).remove();
    
                // update existing rows
                var updatedKeys = [];
                table.rows().every( function () {
                    var oldData = this.data(),
                        newData = message.data.find(function(x) { return x[key] === oldData[key]; });
                    this.data(newData);
                    updatedKeys.push(newData[key]);
                    this.invalidate();
                });
    
                // add missing rows
                table.rows.add(message.data.filter(function(x) {
                    return updatedKeys.find(function (k) { return k === x[key]; }) === undefined;
                }));
                table.draw();
    

    The problem with it is: it acts pretty much like removing all rows and re-adding them because it completely re-creates the TR elements and even the TBODY one.

    Is there any way to avoid that? I would like to update the value in each cell without re-creating the rows and cells.

    EDIT: nevermind, it looks like I was wrong and the rows keep state afterall
    thanks all for your help

This discussion has been closed.