The grid has built in change detection. When a value in the grid changes, either via the UI or via the grid API, the grid will check all cells to see which ones need updating and update exactly only those cells, so minimal changes are made to the DOM.
Change detection can be broken down into the following two categories:
valueGetter'sto be kept up to date where a change to one cell (that was edited) may impact the value of another cell (that references the first cell) - just like Excel!
The example below shows the impact of change detection on value getters. The grid is doing all the refresh by itself with no need for the client application explicitly requesting a refresh. Notice the following:
The grid keeps a local copy of all values rendered in each cell. When a refresh of the cell is requested, the cell will only be refreshed if the value has changed.
This section explains how the grid compares values. This is of interest if you want to compare values in a different way.
By default the grid will compare values by using triple equals, eg "oldValue === newValue". This will work most of the time for you, especially if your values are simple types (string, number, boolean) or immutable objects. This will be a problem for mutable objects as object references will be used for comparison which won't detect internal changes in the object. If using mutable objects (data has changed but it's the same object reference), then you will need to override how the value's are compared.
If your row data attributes are simple types (string, boolean, number) or immutable objects you don't need to implement your own comparison method.
If you do need to provide custom comparison of objects, use the
For example, the following code snippet provides custom comparison to a 'Name' column where the
name is stored in a complex object.
The following operations will automatically trigger change detection on all visible cells:
rowNode.setDataValue(col,value)Row Node method.
If you do not want change detection to be automatically done, then set the grid property
suppressChangeDetection=true. This will stop the change detection process firing
when the above events happen. Ideally you should not want to turn off change detection, however
the option is there if you choose to turn it off. One thing that may entice you to turn it off
is if you have some custom value getters that are doing some time intensive calculations, you may want
limit the number of times they are called and have more control over when refreshing is done.
To manually run value change detection to refresh all visible cells call api.refreshCells().
Aggregation change detection means rerunning aggregations when a value changes. So for example, if you are grouping by a column and summing by a value, and one of those values change, then the summed value should also change.
The example below shows change detection impacting the result of groups. The grid is doing all the refresh by itself with no need for the client application explicitly requesting a refresh. Notice the following:
Notice above that the group column is also editable (eg you can change one of the rows from group 'A' to group 'G'), however the row does not move into the correct group after this change is made. This is discussed below in the section Change Detection and Sorting, Filtering, Grouping.
The following operations will automatically trigger aggregation change detection:
rowNode.setDataValue(col,value)Row Node method.
To manually run aggregation change detection to re-compute the aggregated values, then call api.refreshInMemoryRowModel('aggregate').
When a value changes, the grid's automatic change detection will update:
The reason why sorting, filtering and grouping is not done automatically is that it would be considered bad user experience in most use cases to change the displayed rows while editing. For example, if a user edits a cell, then the row should not jump location (due to sorting and grouping) or even worse, disappear altogether (if the filter removes the row due to the new value failing the filter).
For this reason, if you want to update the sorting, filtering or group grouping
after an update, you should listen for the event
cellValueChanged and call
with the rows that were updated.
The following example is the same as the example above Change Detection and Groups except it gets the grid to do an batch update so that the grouping, sorting and filtering are recomputed. From the example, the following can be noted:
When data in the grid updates and aggregations are active, the grid will not recompute all aggregations again from scratch. Instead it will be selective as to what aggregations need to be re-computed.
When a value changes, the grid will recompute the immediate group the row is in, and then any parent group, all the way to the root. This is known as 'tree path selection' - only the part of the tree that need to be recalculated are recalculated.
If you are updating many rows at the same time using an update transaction, the grid will do all updates first, then recompute all aggregations against the combined impacted paths only.
By default, the grid will recalculate aggregations on all columns for the updated tree path, even if only one of the columns values were changed. This is because the grid assumes any column has the potential to impact any other column, should the column be referenced in a valueGetter.
If you are sure that a value change impacts that one column only, then you can
set the grid property
aggregateOnlyChangedColumns=true. This will re-aggregate
only the changed column and not all columns after a single cell is updated.
Consider the example below and you edit a cell value under under the groups "Bottom" -> "Group B2" and column "Column C". The grid will only recompute column C aggregations for "Group B2" and "Bottom". It will not recompute any aggregates for any other groups or for any other columns.
The tree path selection (ie not updating anything in the group "Top") is active always in the grid
and the column selection (only updating column "Column C") is active because of the grid property
The path selections ensure only the minimal amount of recalculations are done.
To demonstrate this, the example installs it's own aggregation function for summing. This is identical to the normal summing provided by the grid while also printing out to the console when it gets called. This allows the example to show when the aggregations are done and on what.
So with the example below, open up the console and notice the following:
Everything above stands for when you are doing pivoting. There are no new concepts to introduce, so lets just get stuck into an example.
When you click any of the buttons below, remember you are not changing the displayed cells values, as when you pivot, each cell is an aggregation of underlying data and the underlying data is no longer displayed in the grid (doing a pivot removes leaf nodes).
From the example, you can observe:
rowNode.setDataValue(). The grid aggregates the new value for display.
api.updateRowData(transaction). The grid aggregates the new value for display.
api.updateRowData(transaction). The grid does a delta change and adds one more row to represent this group while not touching the DOM with the remaining rows.
api.updateRowData(transaction). This impacts the columns in the grid as we are pivoting on 'course', so a new column is added for 'Physics'. Again this is all done without touching the remaining columns or rows in the grid.
api.updateRowData(transaction). As before, this impacts the columns, all 'Physics' columns are removed.
api.updateRowData(transaction). This results in the aggregations changing in two locations, once where the course was removed, and another where the course was added.