Row Grouping
This section covers Server-side Row Grouping using the Server-side Row Model.
Perhaps the most compelling reason to choose the Server-side Row Model is to achieve lazy-loading of Row Groups.
This section will continue where Infinite Scroll left
off, to cover a more complex scenario which includes Server-side Row Grouping, Aggregation and Sorting.
Group Caches
The Server-side Cache has already
been covered, however in when performing Row Grouping it is important to understand that each group node contains
a cache. This is illustrated in the following diagram:
When a group node is expanded, such as 'Australia' above, a cache will be created and blocks containing rows will be
loaded via the Server-side Datasource
Group Request Parameters
The relevant IServerSideGetRowsRequest parameters for Row Grouping are as follows:
IServerSideGetRowsRequest {
// row group columns
rowGroupCols: ColumnVO[];
// what groups the user is viewing
groupKeys: string[];
... // other params
}
Where rowGroupCols contains all the columns (dimensions) the grid is grouping on, i.e. 'Country', 'Year',
and groupKeys contains the list of group keys selected, i.e. ['Argentina', 2012].
Example - Pre-defined Grouping - Mocked Server
Below shows an example of pre-defined grouping using the olympic winners dataset.
It is pre-defined as we set the grid with specific columns for row grouping and
do not allow the user to change this. Then
the datasource knows that the grid will either be asking for the top level
country list OR the grid will be looking for winners
for a particular country.
In your application, your server-side would know where to get the data based
on what the user is looking for, eg it could go to a relational database
table to get the list of countries and then a web service to get the winners
for the country as the user expands the group (a web service to get the winners
per country is improbable, however the example demonstrates you do not need to
go to the same datastore for the different levels in the grid).
In the example, the work your server would do is mocked for demonstrations
purposes (as the online examples are self contained and do not contact any
servers).
The example demonstrates the following:
- Grouping: The data is grouped by country.
- Aggregation: The server always sum's gold, silver and bronze.
The columns are not set as value columns, and hence the user cannot change
the aggregation function via the column menu. The server just assumes if grouping,
then these columns should be aggregated using a sum function.
- Sorting: The sorting is done on the server-side.
For example, sort by Athlete, then expand a group and you will
see Athlete is sorted.
When the grid sort changes, only impacted rows will get reloaded. For example if grouping by Country
and sort by Athlete changes, the top level Country groups will not get reloaded as sorting by Athlete
will not impact the top level groups.
To avoid this and always refresh top level groups regardless of which column was sorted,
set grid property serverSideSortingAlwaysResets = true.
Providing Child Counts
By default, the grid will not show row counts beside the group names. If you do want
row counts, you need to implement the getChildCount() callback for the
grid. The callback provides you with the row data, it is your applications responsibility
to know what the child row count is. The suggestion is you set this information into
the row data item you provide to the grid.
gridOptions.getChildCount = function(data) {
// in this example, the data has the child count
// stored in the attribute 'childCount'.
return data.childCount;
};
Purging Groups
The grid has the following API to allow you to interact with the server-side cache.
| Method |
Description |
| purgeServerSideCache(route) |
Purges the cache. If you pass no parameters, then the top level cache is purged. To
purge a child cache, then pass in the string of keys to get to the child cache.
For example, to purge the cache two levels down under 'Canada' and then '2002', pass
in the string array ['Canada','2002']. If you purge a cache, then all row nodes
for that cache will be reset to the closed state, and all child caches will be destroyed. |
| getCacheBlockState() |
Returns an object representing the state of the cache. This is useful for debugging and understanding
how the cache is working. |
Below shows the API in action. The following can be noted:
-
Button Purge Everything purges the top level cache.
-
Button Purge [Canada] purges the Canada cache only. To see this in action, make sure you have
Canada expanded.
-
Button Purge [Canada,2002] purges the 2002 cache under Canada only. To see this in action, make
sure you have Canada and then 2002 expanded.
-
Button Print Block State prints the state of the blocks in the cache to the console.
-
The example implements
getChildCount() to set the child count for each group.
Your application is responsible for figuring out the child count (maybe it's an attribute you set
on the data?), the example sets a random number.
Preserving Group State
It may be necessary to expand groups to a desired initial state or to restore the grid to a previous state after
purging / reloading data.
This can be achieved by expanding row nodes as blocks are loaded in the
Server-side Datasource. The following
snippet outlines a possible approach:
function getRows(params) {
// 1) get data from server
var response = getServerResponse(params.request);
// 2) call the success callback
params.successCallback(response.rowsThisBlock, response.lastRow);
// 3) to preserve group state we expand any previously expanded groups for this block
rowsInThisBlock.forEach(row => {
if (expandedGroupIds.indexOf(row.id) > -1) {
gridOptions.api.getRowNode(row.id).setExpanded(true);
}
});
}
Notice that in step 3, newly loaded row nodes for the current block are expanded if they are defined in expandedGroupIds,
which is an array of group keys maintained by the application. This will have a cascading effect as expanding a
group will cause new block(s) to load.
In order to easily look up group row nodes, implementing the following callback is recommended: gridOptions.getRowNodeId().
In the example below, the following can be noted:
- The grid has an initial expanded group state where:
expandedGroupIds = ["Russia", "Russia-2002", "Ireland", "Ireland-2008"]
- The group state is updated in
expandedGroupIds by using listening to the grid event: RowGroupOpened.
- Clicking the 'Purge Caches' button reloads data. Notice that the group state has been preserved.
Next Up
Continue to the next section to learn how to perform Server-side Pivoting.