Master / Detail
This section describes how to nest grids inside grids using a Master / Detail configuration.
enterprise_feature("Master Detail"); ?>With the Master Detail grid configuration, the top level grid is referred to as the 'master grid' and the nested grid is referred to as the 'detail grid'.
With this configuration the detail grid can be used to display more information about the row in the master grid that was expanded to reveal the detail grid.
Enabling Master Detail
To enable Master / Detail, you should set the following grid options:
- masterDetail: Set to true to inform the grid you want to allow expanding of rows to reveal detail grids.
- detailGridOptions: The grid options to set for the detail grid. The detail grid is a fully featured instance of ag-Grid, so any configuration can be set on the detail grid that you would set any other grid.
- getDetailRowData: A function you implement to provide the grid with rows for display in the detail grids.
These grid options are illustrated below:
Example: Simple Master / Detail
Below shows a simple Master / Detail setup. From the example you can notice the following:
- masterDetail - is set to
truein the master grid options. - detailCellRendererParams - specifies the
detailGridOptionsto use andgetDetailRowDataextracts the data for the detail row.
Accessing Detail Grid API
You can access the API of all detail grids via the master grid. The API for each detail grid
is stored in a DetailGridInfo object that has the following properties:
The DetailGridInfo is accessed via the GridApi of the master
gridOptions. You can either reference a particular detail grid API by ID,
or loop through all the existing detail grid APIs.
The DetailGridInfo contains a reference to the underlying Grid API
and Column API for each detail grid. Methods invoked on these API's
will only operate on the specific detail grid.
Example: Editing Cells with Master / Detail
This example shows how to control cell editing when using Master / Detail. This examples demonstrates the following:
- Edit Master - performs editing on a master cell using the master grid options:
masterGridOptions.api.startEditingCell() - Stop Edit Master - iterates over each master row node using
masterGridOptions.api.forEachNodeand then callsmasterGridOptions.api.stopEditing()on each node. - Edit Detail - looks up the corresponding
DetailGridInfousingmasterGridOptions.api.getDetailGridInfo()and then uses the grid api on that detail grid start editing:detailGrid.api.startEditingCell() - Stop Edit Detail - iterates over each detail grid using
masterGridOptions.api.forEachDetailGridInfo()and then callsdetailGridApi.api.stopEditing()on each detail grid.
Syncing Detail scrolling with Master
By default, detail grids scroll independently to the master grid. This happens because the Master Detail is rendered inside the Full Width Row (an element that spans across the Grid Viewport).
To force this full width row to fill the Grid scrollable area, it is necessary to enable the
embedFullWidthRows property.
Example: Details scrolls horizontally with Master
In the example below, notice that horizontal scrolling from within the detail grid also scrolls the master:
Overriding the Default Detail Cell Renderer
The template used by default detail Cell Renderer can be overridden with a user defined template. This is a convenient way to provide custom layouts and styles to the detail rows.
There are two ways to achieve this:
- String Template - statically overrides the template used by the grid. The same fixed template is used for each row.
- Template Callback - called each time a detail row is shown so can dynamically provide a template based on the data.
Both methods require specifying the detailCellRendererParams.template property as shown below:
The template must contain an element with attribute ref="eDetailGrid".
This element is used to host the detail grid instance.
ref="eDetailGrid" must be wrapped inside a div with the height set appropriately.
The following examples demonstrate both approaches.
Example: Customising via String Template
This examples demonstrates a static string template which is supplied to the detailCellRendererParams.template
property to customise the layout and background colour.
Example: Customising via Template Callback
A template callback function is supplied to the detailCellRendererParams.template property to customise
the layout and background colour. It additionally adds the name from the master row using the data supplied via callback parameters.
Providing a Custom Detail Cell Renderer
The previous section described how to override the detail template used in the default Cell Renderer, however it is also possible to provide a custom detail Cell Renderer Component. This approach provides more flexibility but is more difficult to implement as you have to provide your own custom detail cell renderer. Use this approach if you want to add additional functionality to the detail panel that cannot be done by simply changing the template.
To supply a custom detail Cell Renderer instead of using the default use: gridOptions.detailCellRenderer
The following examples demonstrate custom Cell Renderer components for the detail row with and without a grid.
Example: Custom Detail Cell Renderer with a Grid
By the very nature of a custom detail cell renderer it can contain zero or many grid instances. For this reason if you need the master grid to reference it's detail grids you will have to register them manually.
When the detail grid is initialised, register it via masterGridApi.addDetailGridInfo() like so:
And in a similar way unregister it when the detail cell renderer is destroyed using:
For details on how to access the detail grid api see: Accessing Detail Grid API.
This example demonstrates how to embed a grid into the detail row using a custom Cell Renderer component:
Example: Custom Detail Cell Renderer with a Form
This example demonstrates a custom Cell Renderer Component that uses a form rather than a grid:
Configure Grid per Row
The property detailCellRendererParams can be a function to allow providing
different parameters for each row. This can be used to provide a differently configured grid
for each row.
The example below shows different grid configurations based on the data. Note the following:
- Expanding rows 'Mila Smith' or 'Harper Johnson' will use a detail grid with the columns {Call ID, Number}.
- Expanding all other rows will use a detail grid with the columns {Call ID, Direction, Duration, Switch Code}.
Dynamically Specify Master Nodes
It certain cases it may be required to not treat all top level rows as a master rows. For instance if a master has no child records it may not be desirable to expand the master row to an empty detail.
In order to prevent this the following callback can be used on the master grid options:
As shown above our callback function will return true when there are detail (i.e. children) records,
otherwise it will return false.
Example: Dynamically Specify Master Nodes
The following example only shows detail rows when there are corresponding child records.
Nesting Master / Detail
It is possible to nest Master / Detail grids. There are no special configurations required to achieve this, you just configure another detail grid inside the first detail grid.
The following snippet illustrates how to achieve nesting via successive grid option configurations:
Example: Nesting Master / Detail
Below shows a contrived master detail setup to help illustrate how nesting can be achieved. The example has very little data - this is on purpose to focus on the nesting.
Detail Row Height
The height of detail rows can be configured in one of the following two ways:
-
Use property
detailRowHeightto set a fixed height for each detail row. -
Use callback
getRowHeight()to set height for each row individually. One extra complication here is that this method is called for every row in the grid including master rows.
The following snippet compares both approaches:
Note that the detail property can be used to identify detail rows.
The following examples demonstrate both approaches:
Example: Fixed Detail Row Height
The following demonstrates a fixed detail row height:
Example: Dynamic Detail Row Height
The following example demonstrates dynamic detail row heights:
Filtering and Sorting
There are no specific configurations for filtering and sorting with Master / Detail but as there are multiple grids each grid will filter and sort independently.
Example: Filtering with Sort
Below shows a simple Master / Detail setup which has filtering and sorting enabled in both master and detail grids.
Lazy Load Detail Rows
It is possible to lazy load detail row data as it becomes available. For instance an asynchronous request could be sent when expanding a master row to fetch detail records.
The following snippet illustrates this using a simple setTimeout() function to delay supplying
data to the detail row after a fixed timeout.
Note that the key to this approach is the params.successCallback(data) function provided via the params, which can
be invoked later or asynchronously once the data for the detail row is available.
Example: Lazy Load Detail Rows
Below shows a simple Master / Detail setup which uses setTimeout() to simulate lazying loading of data
in the detail rows:
Keeping Detail Rows
When a master row is expanded a detail row is created. When the master row is collapsed, the detail row is destroyed. When the master row is expanded a second time, a detail rows is created again from scratch. This can be undesirable behaviour if there was context in the detail row, e.g. if the user sorted or filtered data in the detail row, the sort or filter will be reset the second time the detail row is displayed.
To prevent losing the context of details rows, the grid provides two properties to cache the details rows to be reused the next time the row is shows. The properties are as follows:
keepDetailRows | Set to true to keep detail rows for when they are displayed again.Default: false |
keepDetailRowsCount | Sets the number of details rows to keep. Default: 10 |
The example below demonstrates keeping detail rows. Note the following:
-
The detail grid has property
keepDetailRows=trueto turn on keeping detail rows. -
The detail grid has property
keepDetailRowsCount=2which sets the number of details rows to keep to 2. - All the detail grids allow moving and sorting columns. If you change the state of a detail grid (e.g. by sorting a detail grid), that state will be kept if you close the parent row and then open the parent row again.
- The maximum number of detail rows kept is two. If you open three detail grids and apply sorting on each grid, then close all three detail grids (so none are showing) and then open the three grids again, only two of the grids will have the sort state kept.
Changing Data & Refresh
By default when updating data using transactions then detail rows / grids get refreshed when there is new data for the master row they belong to. Other rows (where no data change accrued) do not get updated.
This refresh behaviour can be undesirable as the refresh will reset the detail grid loosing any context (eg sorting and filtering in the detail grid will be lost).
To change this behaviour, and never have the detail row / grid refresh, set suppressRefresh
parameter on the detail cell renderer params.
The example below demonstrates changing data without refreshing the detail grids. Note the following:
- The grid refreshes a row each second by incrementing the call count.
- The detail grid never refreshes, thus any sort or filter applied will remain.
suppressRefresh property.
Exporting Master / Detail Data
By default, exporting the master grid will just export the master rows. If you want to export detail rows, you can
configure the getCustomContentBelowRow callback to generate a representation of the detail row that will
be inserted below the master rows in the in the export. See the
export documentation for more details.
There is an important difference between rendering and exporting Master / Detail content. When you expand a master row in the UI, a new instance of the Grid is created to render the detail, meaning that you have the full power of the Grid to sort, filter and format the detail data.
When exporting, the original data object representing
the row is passed to getCustomContentBelowRow which returns styled content to be inserted into the
export. No instance of the Grid is created. This means that export performance is good even with large Master /
Detail data sets. However, if your detailGridOptions contains value getters, value formatters,
sorting, filtering etc, and you want these to appear in the export, they must be applied by
getCustomContentBelowRow.
Example: Exporting Master / Detail Data
The example below demonstrate how both master and detail data can be exported.
Supported Modes
The Master / Detail feature organises the grid in a way which overlaps with other features. For example, Master / Detail expands rows, which is also the case with row grouping. For this reason, Master / Detail does not work with certain grid configurations. These configurations are listed below:
Row Models
The master grid (i.e. the top level grid) in Master / Detail can be used in the Client-side and Server-side Row Models. However it is not supported with the Viewport or Infinite Row Models.
The detail grid (i.e. the child grid) can use any Row Model, as long as the master grid uses the Client-side or Server-side Row Models, then the detail grid can use any of the other row models.
Tree Data
Master / Detail is not supported with Tree Data. This is because the concept of tree data conflicts with Master / Detail, in that in tree data, any row can expand to show child rows, which would result in a clash when a row has child rows in addition to having Master / Detail at the same row.
Layouts
It is not possible to mix DOM layout for master detail. This is because the layout is a CSS setting that would be inherited by all grids contained with the master grid. So if your master grid was 'for-print', then all child grids would pick up the 'for-print' layout.
When using Master / Detail and for-print, then all detail grids need to use for-print.
When using Master / Detail and auto-height, then all detail grids need to use auto-height.