Expand All

  Getting Started



  Row Models





Github stars make projects look great. Please help, donate a star, it's free.
Read about ag-Grid's Partnership with webpack.
Get informed on releases and other ag-Grid news only - never spam.
Follow on Twitter

Enterprise Row Model

The Enterprise Row Model is arguably the most powerful of the row models in ag-Grid and presents the ultimate 'big data' user experience, allowing the user to navigate through very large data sets using a mixture of server side grouping and aggregation while using infinite scrolling to bring the data back in blocks to the client.

Enterprise Row Model Features

The best way to learn what the Enterprise Model does is to break it down into the core features. You may benefit from the combination of all these features or just be interested in a subset. The features of the enterprise row model are:

  • Lazy Loading of Groups: The grid will load the top level rows only. Children of groups are only loaded when the user expands the group. Some applications may use the Enterprise Row Model for this one feature alone e.g. you might have a managers database table, you can display a list of all managers, then click 'expand' on the manager and the grid will then request to get the 'employees' for that manager.
  • Server Side Grouping, Pivot and Aggregation: Because the data is coming back from the server one group level at a time, this allows you to do aggregation on the server, returning back the aggregated results for the top level parent rows. For example you could include 'employee count' as an attribute on the returned manager record, to say how many employees a manager manages.
  • Infinite Scrolling: Rows are read back from the server in blocks to provide the experience of infinite scrolling. This happens at each grouping level (ie the top level rows are brought back in blocks, then when you expand a group, the children of that group are also loaded in blocks). This allows viewing very large datasets in the browser by only bringing back data one block at a time. This feature reuses the logic from the Infinite Scrolling row model, so understanding how that row model works will help you in understanding this part of the enterprise row model.
  • Slice and Dice: Assuming your server side can build the data query, you can allow the user to use the ag-Grid UI to drag columns around to select what columns you want to group by and aggregate on. What the user selects will then be forwarded to your datasource as part of the request. This feature is advanced and will require some difficult server side coding from you, however if done correctly then your users will have an experience of slicing and dicing large data in real time, something previously only available in expensive reporting tools, now you can embed it into your JavaScript application.

Enterprise Datasource

Similar to the Infinite Scrolling and Viewport row models, you provide the grid with a datasource. The interface for the datasource is as follows:

// datasource for enterprise row model interface IEnterpriseDatasource { // just one method, to get the rows getRows(params: IEnterpriseGetRowsParams): void; }

Each time the grid requires more rows, it will call the getRows() method. The method is passed a params object that contains two callbacks (one for success and one for failure) and a request object with details what row the grid is looking for. The interface for the params is as follows:

interface IEnterpriseGetRowsParams { // details for the request request: IEnterpriseGetRowsRequest; // success callback, pass the rows back the grid asked for. // if the total row count is known, provide it via lastRow, so the // grid can adjust the scrollbar accordingly. successCallback(rowsThisPage: any[], lastRow: number): void; // fail callback, tell the grid the call failed so it can adjust its state failCallback(): void; }

The request gives details on what the grid is looking for. The success and failure callbacks are not included inside the request object to keep the request object simple data (ie simple data types, no functions). This allows the request object to be serialised (eg via JSON) and sent to your server. The request has the following interface:

interface IEnterpriseGetRowsRequest { // row group columns rowGroupCols: ColumnVO[]; // value columns valueCols: ColumnVO[]; // pivot columns pivotCols: ColumnVO[]; // true if pivot mode is one, otherwise false pivotMode: boolean; // what groups the user is viewing groupKeys: string[]; // if filtering, what the filter model is filterModel: any; // if sorting, what the sort model is sortModel: any; } // we pass a VO (Value Object) of the column and not the column itself, // so the data can be converted to a JSON string and passed to server side export interface ColumnVO { id: string; displayName: string; field: string; aggFunc: string; }

Studying the interfaces above alone probably won't describe the whole story in an understandable way. The best thing to do is look at the examples below and debug through them with the web console and observe what is passed back as you interact with the grid.

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, similar to filtering, is done on the server side. For example, sort by Athlete, then expand a group and you will see Athlete is sorted.

Example - Slice and Dice - Mocked Server

The concept of 'Slice and Dice' means the user can decide what they want to group, aggregate and pivot on by dragging the columns around in the grid.

When the user changes the status of the columns (ie the user changes how the data is grouped, aggregated or pivoted) then the grid data is cleared out and loaded again from scratch using the new configuration.

A mock data store running inside the browser is used in the below example. The purpose of the mock server is to demonstrate the interaction between the grid and the server. For your application, your server side would need to understand the requests from the client and build SQL (or the SQL equivalent if using a no-SQL data store) to run the relevant query against the data store.

The example demonstrates the following:

  • Columns Athlete, Age, Country, Year and Sport all have enableRowGroup=true which means they can be grouped on. To group you drag the columns to the row group panel section. By default the example is grouping by Country and then Year as these columns have rowGroup=true.
  • Columns Gold, Silver and Bronze all have enableValue=true which means they can be aggregated on. To aggregate you drag the column to the Values section. When you are grouping, then all columns in the Values section will be aggregated.
  • You can turn the grid into Pivot Mode. To do this, you click the pivot mode checkbox. When the grid is in pivot mode, the grid behaves similar to an Excel grid. This extra information is passed to your server as part of the request and it is your servers responsibility to return the data in the correct structure.
  • Columns Gold, Silver and Bronze all have enablePivot=true which means they can be pivoted on when Pivot Mode is active. To pivot you drag the column to the Pivot section.
  • Note that when you pivot, it is not possible to drill all the way down the leaf levels.
  • In addition to grouping, aggregation and pivot, the example also demonstrates filtering. The columns Age, Country and Year all have a filter.

When filtering using the Enterprise Row Model it's important to specify the filter parameter: newRowsAction: 'keep'. This is to prevent the filter from being reset as data is loaded into the grid.

Pivoting Challenges

Achieving pivot on the server side is difficult. If you manage to implement it, you deserve lots of credit from your team and possibly a few hugs (disclaimer, we are not responsible for any inappropriate hugs you try). Here are some quick references on how you can achieve pivot in different relational databases:

All databases will either implement pivot (like Oracle) or require you to fake it (like MySQL).

To understand Pivot Mode and Secondary Columns please refer to the relevant sections on Pivoting in In Memory Row Model. The concepts mean the same in both In Memory Row Model and the Enterprise Row Model.

Secondary columns are the columns that are created as part of the pivot function. You must provide these to the grid in order for the grid to display the correct columns for the active pivot function. For example, if you pivot on Year, you need to tell the grid to create columns for 2000, 2002, 2004, 2006, 2008, 2010 and 2012.

Secondary columns are defined identically to primary columns, you provide a list of Column Definitions to the grid. The columns are set by calling columnApi.setSecondaryColumns() and passing a list of columns and / or column groups. There is no limit or restriction as to the number of columns or groups you pass - the only thing you should ensure is that the field (or value getter) that you set for the columns matches.

If you do pass in secondary columns with the server response, be aware that setting secondary columns will reset all secondary column state. For example if resize or reorder the columns, then setting the secondary columns again will reset this. In the example above, a hash function is applied to the secondary columns to check if they are the same as the last time the server was asked to process a request. This is the examples way to make sure the secondary columns are only set into the grid when they have actually changed.

If you do not want pivot in your enterprise row model grid, then you can remove it from the tool panel by setting toolPanelSuppressPivotMode=true and toolPanelSuppressValues=true.

Example - Slice and Dice - Real Server

It is not possible to put up a full end to end example of the Enterprise row model on the documentation website, as we cannot host servers on our website. Instead we have put a full end to end example in Github at https://github.com/ag-grid/ag-grid-enterprise-mysql-sample/.

The example puts all the olympic winners data into a MySQL database and creates SQL on the fly based on what the user is querying. This is a full end to end example of the type of slicing and dicing we want ag-Grid to be able to do in your enterprise applications.

The example does not demonstrate pivoting. This is because pivot is not easily achievable in MySQL.

The example is provided to show what logic you will need on the server side. It is provided 'as is' and we hope you find it useful. It is not provided as part of the ag-Grid Enterprise product, and as such it is not something we intend to enhance and support. It is our intention for ag-Grid users to create their own server side connectors to connect into their bespoke data stores. In the future, depending on customer demand, we may provide connectors to server sides stores.

Selection with Enterprise Row Model

Selecting rows and groups in the enterprise row model is supported. Just set the property rowSelection to either single or multiple as with any other row model.

Selecting Group Nodes

When you select a group, the children of that group may or may not be loaded into the grid. For this reason the setting groupSelectsChildren=true (which selects all the children of the group when you select a group) does not make sense. When you select a group, the group row only will be marked as selected.

Example - Click Selection

The example below shows both simple 'click' selection as well as multiple 'shift-click' selections. Selecting groups is not allowed as clicking on groups is reserved for opening and closing the groups.

  • Single 'Click' Selection - when you click on a leaf level row, the row is selected.
  • Multiple 'Shift-Click' Selections - select a leaf row (single click) and then 'shift-click' another leaf row within the same group to select all rows between that range.

Performing multiple row selections using 'shift-click' has the following restrictions:
  • Only works across rows that share the same parent.
  • Only works for rows that are loaded (eg a large range selection may span rows that are not loaded).

Example - Checkbox Selection

Below shows another example using checkbox selection. The example shows:

  • Checkbox selection on the group column allowing selection of any row.
  • Checkbox selection on the group year column allowing selection on leaf level rows only.
The example shows checkboxes on two columns. This is for comparison in the example only. Normal applications generally have the checkbox only on one column.

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; };

Providing Node ID's

Providing node ID's is optional. If you provide your own node id's (using the getRowNodeId() callback) then you must make sure that the rows have unique ID's across your entire data set. This means all the groups and all leaf level nodes must have unique id's, even if the leafs are not part of the same group. This is because the grid uses node id's internally and requires them to be unique.

If you do not provide node id's, the grid will provide the id's for you, and will make sure they are unique.

Dynamic Row Height

To enable Dynamic Row Height when using the enterprise row model you need to provide an implementation for the 'getRowHeight' Grid Options property. This is demonstrated in the example below:

Purging the cache and dynamic row heights do not work together for the Enterprise Row Model. If you are using dynamic row height, ensure 'maxBlocksInCache' is not set.

Enterprise Model API

The grid has the following API to allow you to interact with the enterprise cache.

Method Description

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.

getEnterprisePageState() 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.

Pagination with Enterprise Row Model

To enable pagination when using the enterprise row model, all you have to do is turning pagination on with pagination=true. Find an example below: