Updating Data

This section explains how to update the grid's data using the grid's API's.

As well as using the grid's API's, the grid also allows updating data in the following other ways which are explained in other sections of the documentation:

  1. Using the grid's in-line editing feature, eg double clicking on a cell and editing the value.
  2. Updating the data directly in your application - which the grid is not aware of the changes and you need to tell the grid to refresh the view.

This section of the documentation is regarding using the grid's API to update data. The grid will then be aware of the change and also update the relevant parts of the UI.

If you are using an immutable data store, as is usual in a React application, then you will be interested in the section below Bulk Method 3 - Delta Row Data.

Note that this is only applicable if you are using the Client-side Row Model. If you are using viewport or Server-side the data would be passed to the grid through a datasource and the specifics on how to update each model would be explained in their respective docs.

Updating RowNodes Data

You can set the data onto a rowNode directly using the rowNodes API methods:

  • rowNode.setData(data): Replaces the data on the rowNode. When complete, the grid will refresh the the entire rendered row if it is showing.
  • rowNode.setDataValue(colKey, value): Replaces the data on the rowNode for the specified column. When complete, the grid will refresh the rendered cell on the required row only.

Updating via the rowNode methods is supported in all row models.

Updating data via the rowNode methods will refresh the grid for the required rows if they are showing, however it will not update the grids sorting, filtering or grouping if the new data impacts such. For that, you should use an update transaction as explained below.

Updating data using rowNode.setData() and rowNode.setDataValue() do not update the sorting, filtering or grouping. Using an update transaction (explained below) does update the sorting, filtering and grouping.

If you are using Client-side Row Model and you want to get the grid to update it's sort or filter etc after the update is done, then you must call api.refreshClientSideRowModel(step) where step can be one of the following: group, filter, map, aggregate, sort, pivot.

The Client-side Row Model has stages as follows:

  • Group ⇒ Filter ⇒ Pivot ⇒ Aggregate ⇒ Sort ⇒ Map

That means, if you call api.refreshClientSideRowModel('filter'), it will also execute pivot, aggregate, sort and map.

Updating RowNodes Data Example

The example below demonstrates the following:

  • Set Price on Toyota: The price value is updated on the Toyota row and the grid refreshes the cell.
  • Set Data on Ford: The entire data is set on the Ford row and the grid refreshes the entire row.
  • Sort: Re-runs the sort in the Client-side Row Model - to see this in action, sort the data first, then edit the data so the sort is broken, then hit this button to fix the sort.
  • Filter: Re-runs the filter in the Client-side Row Model - to see this in action, filter the data first, then edit the data so the filter is broken (ie a row is present that should not be present), then hit this button to fix the filter.

Full CRUD & Bulk Updating

If you want to add, remove or update more than one row at a time, then you have the following options:

  • Method 1 - Row Data (Normal)

    The next way is to replace all the row data in the grid be calling api.setRowData(newData) or by binding new data to the rowData property (if using a framework such as Angular or React that allow data binding). This is the default method. The grid will discard all previous data and create the rowNodes again from scratch. All row and range selection will be lost.

    Use this method if you are effectively loading brand new data into the grid, eg loading a new report with a completely different data set to the previous. This makes sure nothing is lying around from the old dataset.

  • Method 2 - Transaction

    The transaction method is to pass a transaction object to the grid containing rows to add, remove and update. This is done using api.updateRowData(transaction). The grid keeps all active sorting, grouping and filtering, including updating to reflect the changes in the data should the sorting, grouping or filtering be impacted.

    Updating using transactions is the best way to do large updates to the grid, as the grid treats them as delta changes, so the grid only refreshes what is needed giving a performance boost. All row and range selection will be kept.

  • Method 3 - Delta Row Data

    The delta method is using the row data method above but having the property deltaRowDataMode=true.

    When deltaRowDataMode is on, the grid will compare the new row data with the current row data and create a transaction object for you. The grid then executes the change as an update transaction, keeping all of the grids selections, filters etc.

    Use this if you want to manage the data outside of the grid (eg in a Redux store) and then let the grid work out what changes are needed to keep the grid's version of the data up to date.

  • Method 4 - Batch Update

    The batch method is for when you need the fastest possible way to update many continuous updates, such as providing a stream of updates to the grid. This is done using the API batchUpdateRowData().

    Use the batch update method if you need a high performing grid showing live streaming updates.

Bulk Method 1 - Row Data (Normal)

This is the simplest of the update methods. When you call api.setRowData(newData), the grid discards all previous selections and filters, and completely overwrites the old data with the new. This was the first way the grid worked and is the most 'brute force' way.

Use this method if you want to load the grid with a brand new set of data.

The method api.setRowData() works with the Client-side Row Model only. All of the other row models use a data source and hence it doesn't make sense.

Bulk Method 2 - Transaction

The api.updateRowData(transaction) takes details of what data items to update and then returns all the impacted row nodes.

// API method for updating data function updateRowData(rowDataTransaction: RowDataTransaction): RowNodeTransaction; // params for above interface RowDataTransaction { // rows to add add?: any[]; // index for rows to add addIndex?: number; // rows to remove remove?: any[]; // rows to update update?: any[]; } // result for above interface RowNodeTransaction { // Row Nodes added add: RowNode[]; // Row Nodes removed remove: RowNode[]; // Row Nodes updated update: RowNode[]; }

Adding Rows

The grid will create one new row for each item in the transaction.add array.

The index to add is put in for historical purposes and should not be used. If you want the grid to display in a certain order, you should set deltaRowDataMode=true and then set row data, which will maintain the row order while also working out the update, deletes and adds for you.

Removing Rows

The grid will remove one row for each item in the transaction.remove array.

If you are providing rowNode ID's (via the getRowNodeId() callback) then pass an array of objects with keys corresponding to the rowNodeId you specified with getRowNodeId and values matching the rows you want to remove. If you are not using ID's, then the grid will match the rows based on object reference.

Updating Rows

The grid will update one row for each item in the transaction.update array. Behind the scenes, the grid will call rowNode.setRowData(newData).

Similar to removing, the grid will use node ID's if you are providing your own ID's, otherwise it will use object reference to identify rows.

For adding and removing rows using a transaction, the grid will match rows based on ID's if you are providing your own rowNode ID's. Otherwise it will use object references.

Supported Row Models

The Client-side Row Model fully supports the api.updateRowData() call. The Infinite Row Model supports 'add' only (see the infinite docs for examples). The Viewport Row Model and Server-side Row Model do not support transaction updates.

Example: Updating with Transaction

The example uses the updateRowData method in different ways and prints the results of the call to the console. The following can be noted:

  • Add Row: Adds a row to the end of the list.
  • Insert Row @ 2: Inserts a row at position 2 in the list. This works in the grid as it doesn't allow sorting, filtering or grouping (all of these would impact the order).
  • Update First 5: Updates the price on the first 5 items in the list (add some items first so you have at least 5).
  • Remove Selected: Removes all the selected rows from the list.
  • Get Row Data: Prints all row data in the grid to the console.
  • Clear Data: Sets the data in the grid to an empty list.
  • Add Items: Adds three items.
  • Add Items: Adds three items at position 2.

Example: Updating with Transaction and Groups

When using transactions and grouping, the groups are kept intact as you add, remove and update rows. The example below demonstrates the following:

  • Add For Sale: Adds a new item to 'For Sale' group.
  • Add In Workshop: Adds a new item to 'In Workshop' group.
  • Remove Selected: Removes all selected items.
  • Move to For Sale: Move selected items to 'For Sale' group.
  • Move to In Workshop: Move selected items to 'In Workshop' group.
  • Move to Sold: Move selected items to 'Sold' group.
  • Get Row Data: Prints all row data to the console.

Things to try with the below example include:

  • Move rows between groups, see how the grid animates the rows to the new location with minimal DOM updates.
  • Order by 'Created' and then add rows - notice how the new rows are always added to the top as they are ordered 'latest first'

Bulk Method 3 - Delta Row Data

If you turn on deltaRowDataMode (set the property deltaRowDataMode=true), then when you call api.setRowData(rowData) the grid will work out which items are to be added, removed and updated.

For this to work, you must be treating your data as immutable. This means instead of updating records, you should replace the record with a new object.

The deltaRowDataMode is designed to allow ag-Grid work with immutable stores such as Redux. In an immutable store, a new list of rowData is created if any row within it is added, removed or updated. If using React and Redux, consider setting deltaRowDataMode=true and bind your Redux managed data to the rowData property.

You can also use this technique in a non-Redux or immutable store based application (which is the case in the examples on this page). As long as you understand what is happening, if it fits your applications needs, then use it.

For the deltaRowDataMode to work, you must be providing ID's for the row nodes by implementing the getRowNodeId() callback.

The grid works out the delta changes with the following rules:

  • IF the ID for the new item doesn't have a corresponding item already in the grid THEN it's an 'add'.
  • IF the ID for the new item does have a corresponding item in the grid THEN compare the object references. If the object references are different, it's an update, otherwise it's nothing (excluded from the transaction).
  • IF there are items in the grid for which there are no corresponding items in the new data, THEN it's a 'remove'.

Example: Immutable Store

The example below shows the immutable store in action. The example keeps a store of data locally. Each time the user does an update, the local store is replaced with a new store with the next data, and then api.setRowData(store) is called. This results in the grid making delta changes because we have set deltaRowDataMode=true.

If using React and Redux, simply map the store to the rowData property instead of calling api.setRowData().

The example demonstrates the following:

  • Append Items: Adds five items to the end (assuming when no sort applied *).
  • Prepend Items: Adds five items to the start (assuming when no sort applied *).
  • Reverse: Reverses the order of the items (assuming when no sort applied *).
  • Remove Selected: Removes the selected items. Try selecting multiple rows (ctrl + click for multiple, or shift + click for range) and remove multiple rows at the same time. Notice how the remaining rows animate to new positions.
  • Update Prices: Updates all the prices. Try ordering by price and notice the order change as the prices change. Also try highlighting a range on prices and see the aggregations appear in the status bar. As you update the prices, the aggregation values recalculate.
  • Turn Grouping On / Off: To turn grouping by symbol on and off.
  • Group Selected A / B / C: With grouping on, hit the buttons A, B and C to move selected items to that group. Notice how the rows animate to the new position.
*assuming no sort is applied - because if the grid is sorting, then the grid sort will override any order in the provided data.

Example: Immutable Store - Updates via Feed

Finally, lets go bananas with delta updates. Below is a simplistic trading hierarchy with over 11,000 rows with aggregations turned on. It has the following features:

  • Update Using Transaction: Updates a small bunch of rows by creating a transaction with some rows to add, remove and update.
  • Update Using Delta updates: Same impact as the above, except it uses the delta updates with the grid. Thus it demonstrates both methods working side by side.
  • Start Feed: Starts a feed whereby a transaction of data is processed every couple of seconds. This is intended to demonstrate a large grid with aggregations taking delta updates over the feed. The grids aggregations are updated on the fly to keep the summary values up to date.

This example is best viewed in a new tab. It demonstrates a combination of features working together. In particular you should notice the grid is managing a very large set of data, applying delta updates to the data and only updating the UI where the updates have an impact (as opposed to recalculating everything from scratch when new values come in an requiring a full grid refresh). This gives a fast smooth user experience.

You should also notice that all row selections, range selections, filters, sorting etc work even though the grid data is constantly updating.

Bulk Method 4 - Batch Transactions

Every time you update data in the grid, the grid will rework all aggregations, sorts and filters and the browser will repaint. If you are streaming multiple updates into the grid this can be a bottleneck. Using Batch Transactions will speed up the process by moving the updates into batches.

When you call batchUpdateRowData() the grid will execute the update, along with any other updates you subsequently provide using batchUpdateRowData(), after 50ms.

To help understand the interface into updateRowData() and batchUpdateRowData(), here are both method signatures side by side. The first executes immediately. The second executes sometime later using a callback for providing a result.

// normal updateRowData takes a RowDataTransaction and returns a RowNodeTransaction updateRowData(rowDataTransaction: RowDataTransaction): RowNodeTransaction // batch takes a RowDataTransaction and the result is provided some time later via a callback batchUpdateRowData(rowDataTransaction: RowDataTransaction, callback?: (res: RowNodeTransaction)=>void): void

The default wait between executing batches if 50ms. This can be changed using the grid property batchUpdateWaitMillis.

Use batch updates if you have streaming data going into the grid and want don't want the grid's rendering and recalculating to be a bottleneck.

Small Changes in Large Grouped Data

When grouping, the grid will group, sort, filter and aggregate each individual group. When there is a lot of data and a lot of groups then this results in a lot of computation required for all the data operations.

If using transaction updates then the grid does not execute all the operations (sort, filter etc) on all the rows. Instead it only re-computes what was impacted by a transaction.

For example, if items are grouped by city, and a value for each city is summed at the city level, then if the value changes for one item, only the aggregation for the city it belongs to needs be recomputed. All other groups where data did not change do not need to be recomputed.

Deciding what groups need to be operated on again is called Changed Path Selection. After the grid applies all adds, removes and updates from a transaction, it works out what groups got impacted and only executes the required operations on those groups.

Under the hood delta row data uses transactions in the grid, so Changed Path Selection applies also when using delta row update.

The example below demonstrates Changed Path Selection. The example is best view with the dev console open so log messages can be observed. Note the following:

  • The 'Linux Distro' column is sorted with a custom comparator. The comparator records how many times it is called.
  • The Value column is aggregated with a custom aggregator. The aggregator records how many times it is called.
  • When the example first loads, all the data is set into the grid which results in 171 aggregation operations (one for each group), 48,131 comparisons (for sorting all rows in each group) and 10,000 filter passes (one for each row). The number of milliseconds to complete the operation is also printed (this value will depend on your hardware).
  • Select a row and click 'Update', 'Delete' OR 'Duplicate' (duplicate results in an add operation). Note in the console that the number of aggregations, compares and filters is drastically less. The total time to execute is also drastically less

Note that the example above also uses the following properties to gain performance:

  • suppressMaintainUnsortedOrder: When doing delta updates, the grid stores the data in the same order as the data was provided. For example if you provide a new list with data added in the middle of the list, the grid will also put the data into the middle of the list rather than just appending to the end. This decides the order of data when there is no grid sort applied. If this is not required by your application, then you can suppress this behaviour by setting suppressMaintainUnsortedOrder=true.
  • suppressAggAtRootLevel: When aggregations are present, the grid also aggregates all the top level rows into one parent row. This total aggregation is not shown in the grid so a speed increase can be produced by turning this top level aggregation of by setting suppressAggAtRootLevel=true. It is the intention that a future release of the grid will allow exposing the top level aggregation hence why this feature is left in.

Also note that the example above does NOT do the following (again for performance reasons):

  • Header Checkbox Selection: Header Checkbox Selection will slow the grid down marginally as it requires each row to be checked (for selection state) between each update. If you need a blasting fast grid managing rapid changes, then consider avoiding this feature.

Flashing Data Changes

If you want the grid to flash the cell when the data changes, set attribute colDef.enableCellChangeFlash=true. In the example below, when you click 'Update Some Data', the data is changed in 20 random cells and the grid flashes the cells.

This is a simple and quick way to visually show to the user that the data has changed. It is also possible to have more intelligent animations by putting animations into custom cell renderers. Check out the grid provided animation cell renderers or look at implementing your own refresh in a custom cell renderer.

One exception to the above is changes due to filtering. If you are Row Grouping the data with Aggregations, then the aggregated values will change as filtering adds and removes rows contained within the groups. It typically doesn't make sense to flash these changes when it's due to a filter change, as filtering would impact many (possibly all) cells at once, thus not usefully bringing the users attention to any particular cell. If you do not like this exception and would like to flash changes even when it's the result of a filter change, then set gridOptions.allowShowChangeAfterFilter=true.

You can also explicitly flash cells using the grid API flashCells(params). The params takes a list of columns and rows to flash, e.g. to flash one cell pass in one column and one row that identifies that cell.

The example below demonstrates cell flashing. The following can be noted:

  • All columns have enableCellChangeFlash=true so changes to the columns values will flash.
  • Clicking Update Some Data will update a bunch of data. The grid will then flash the cells where data has changed.
  • Clicking Flash One Cell provides the API flashCells() with one column and one row to flash one cell.
  • Clicking Flash Two Rows provides the API flashCells() with two row nodes only to flash the two rows.
  • Clicking Flash Two Columns provides the API flashCells() with two columns only to flash the two columns.

How Flashing Works

Each time the call value is changed, the grid adds the CSS class ag-cell-data-changed for 500ms, and then then CSS class ag-cell-data-changed-animation for 1,000ms. The grid provide themes use this to apply a background color (for the first 500ms) and then a fade out transition (for the remaining 1,000ms).

If you want to override how the flash presents itself (eg change the background color, or remove the animation) then override the relevant CSS classes.