How to update table and apply existing filters

2.9k views Asked by At

We are using the excellent Tabulator JS library. We poll our server at intervals to refresh the data in our table. We are trying to achieve the following behaviour when this happens.

  1. Update the existing data in the table
  2. Add any new rows that "Match" the current filters
  3. Remove any rows that have changed and don't match the filters
  4. Keep the existing scroll position
  5. Keep any selected rows.
  6. If the filters are removed show the latest data.

There are 3 methods to update Tabulator

http://tabulator.info/docs/4.5/update

  1. SetData (we use this when we first fetch)
  2. updateData
  3. updateOrAddData (we use this on repeated fetches but row edits don't get filtered out)
  4. replaceData

In the documents is mentions that 'replaceData' will update existing table data with out resetting the scroll position or selected rows, this does not seem to be the case. 'updateData' does update the data and leaves the scroll pos and selected rows as is, BUT it does not apply the filters, for example if a row is updated out of the scope of the current filter it still shows?

Our code right now:

if (replace) {
   table.updateOrAddData(data); //replaceData
} else {
   table.setData(data);
}

We need the table to update and meet our requirements in my above points 1-6. I would expect one of the methods listed (replace, update) would do this and in the docs it seems they should, but in our tests this fails. How can we achieve the desired results?

We are using version 4.5 downgraded from 4.4.

Edit:

So for example if we update the table with data and one of the rows in the table does not exist in the new data, that update does not persist. Unless we use setData which resets the scroll position, undoes all selected rows and so on.

4

There are 4 answers

0
Lil Devil On

The latest version of Tabulator, 4.9, adds a refreshFilter function. This should accomplish most of your request.

My own testing also show that the sorters are also refreshed by this function.

table.refreshFilter();

1
dota2pro On

You can either call manually Redraw

table.redraw(true); //trigger full rerender including all data and rows

or just use reactive data

reactiveData:true, //enable reactive data
data:tableData, //assign data array
0
MartinWebb On

After much searching and looking through Tabulator 4.5 docs it seems that the table can not update existing data, re-apply filters, remove dead rows (those not in the new data from the server) from one of the update, replace methods. From what I can understand this can be achieved by the code I have written below, which uses the updateOrAddData method, the setFilter method and my own async function to loop the table and remove dead rows.

    // var data= new data from server - any array.
    // get the existing filters, update the data or add any new rows.
    var f = table.getFilters();
        table.updateOrAddData(data); //replaceData with server copy

        var keys = [],
            r = table.getRows();
        // make a list of all the  keys in our server data, this will make it faster to remove dead rows.
        data.forEach(function(item) { keys.push(item.id); });
        // remove any dead rows in the data that do not belong start at row 0
        removeDeadRows(0, function() {
            table.setFilter(f); //re-apply filters when finished.
        });

    // iterate the table test if each row is in our key list, if not remove it.
        function removeDeadRows(pos, cb) {
            if (!r[pos]) return cb();
            var c = pos + 1;
            try {
                if (keys.indexOf(r[pos].getData().id) > 0) return removeDeadRows(c, cb);
                r[pos].delete();
                removeDeadRows(c, cb);
            } catch (e) {
                console.log(e);
                cb();
            }
        }
7
Michael O'Keefe On

if I understand your OP, this is what you were looking for ?

var selected,visible;
var t = new Tabulator("#tabulator", {
    data:[
        {id:1,title:'One'},{id:2,title:'Two'},{id:3,title:'Three'},{id:4,title:'Four'},{id:5,title:'Five'},
        {id:11,title:'Eleven'},{id:12,title:'Twelve'},{id:13,title:'Thirteen'},{id:14,title:'Fourteen'},{id:15,title:'Fifteen'},
    ],
    height:"10em",
    selectable:true,
    columns:[ {title:'Title',field:'title',headerFilter:'input'}, ],
    initialHeaderFilter:[{field:'title',value:'e'}],
    dataLoading:function(d) { if (t) { selected = t.getSelectedData().map(o => o['id']); visible = t.getData('visible').map(o => o['id']); } },
    dataLoaded:function(d) { if (t) { t.selectRow(selected); t.scrollToRow(visible); } }
});
t.selectRow([3,11,15]);
t.scrollToRow(15);
setTimeout(() => {
    t.replaceData([
        {id:3,title:'Three'},{id:5,title:'Five'},{id:6,title:'Six'},{id:7,title:'Seven'},{id:8,title:'Eight'},{id:9,title:'Nine'},{id:10,title:'Ten'},
        {id:13,title:'Thirteen'},{id:15,title:'Fifteen'},{id:16,title:'Sixteen'},{id:17,title:'Seventeen'},{id:18,title:'Eighteen'},{id:19,title:'Nineteen'},{id:20,title:'Twenty'},
    ]);
},5000);