Angular Tree Grid Group By
If you have non-hierarchical data and you want to group by one or more columns and populate the parent rows with aggregated values, you could use the IgxTreeGridComponent
along with treeGridGrouping
pipe and the UI component with selector igx-tree-grid-group-by-area
.
The treeGridGrouping
pipe groups the data based on the provided parameters and the resulting hierarchy is displayed in a separate column. The pipe can also calculate aggregated values for the generated parent rows if aggregations are provided. Here is an example of how to use the pipe in the template:
<igx-tree-grid #grid
[data]="data | treeGridGrouping:groupingExpressions:groupKey:childDataKey:grid:aggregations"
[childDataKey]="childDataKey"
[sortStrategy]="sorting">
The pipe arguments are the following:
- groupingExpressions - an array of
IGroupingExpression
objects which contains information about the fields used to generate the hierarchy and the sorting details for each group - groupKey - a string value for the name of the generated hierarchy column
- childDataKey - a string value for the field where the child collection of the generated parent rows is stored
- grid -
IgxTreeGridComponent
that is used for the grouping - aggregations (optional) - an array of
ITreeGridAggregation
objects which contains information about the aggregation functions
The UI component with selector igx-tree-grid-group-by-area
handles the UI interactions related to the columns that are used for the grouping. Here is an example of how to use the component in the template:
<igx-tree-grid-group-by-area
[grid]='grid'
[(expressions)]='groupingExpressions'
[hideGroupedColumns]='true'>
</igx-tree-grid-group-by-area>
The component's inputs are the following:
- grid -
IgxTreeGridComponent
that is used for the grouping - expressions - an array of
IGroupingExpression
objects which contains the fields used to generate the hierarchy - hideGroupedColumns - a boolean value indicating whether to hide the columns by which grouping was performed
- dropAreaTemplate - a template for the drop area that can be used to override the default drop area template
- dropAreaMessage - a string that can be used to override the default message for the default drop area template
Note
In order for the sorting to work correctly you should set the sortStrategy
property of the IgxTreeGridComponent
to an instance of IgxGroupedTreeGridSorting
.
Angular Tree Grid Group By Example
Implementation
In this sample we are using the treeGridGrouping
pipe and the UI component with selector igx-tree-grid-group-by-area
for the grouping. The data is grouped by the "category", "type" and "contract" fields. The resulting hierarchy is displayed in the newly created "categories" column. The pipe also calculates aggregated values for the generated parent rows for the "price", "change" and "changeP" columns.
<igx-tree-grid #grid1
[data]="data$ | async | treeGridGrouping:groupingExpressions:groupColumnKey:childDataKey:grid1:aggregations"
[childDataKey]="childDataKey"
[sortStrategy]="sorting">
<igx-tree-grid-group-by-area
[grid]="grid1"
[(expressions)]="groupingExpressions"
[hideGroupedColumns]="true">
</igx-tree-grid-group-by-area>
<igx-column [field]="groupColumnKey"></igx-column>
Here you can see how the grouping expressions and aggregations are defined:
public groupingExpressions: IGroupingExpression[] = [
{ fieldName: 'category', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance() },
{ fieldName: 'type', dir: 1, ignoreCase: true, strategy: DefaultSortingStrategy.instance() },
{ fieldName: 'contract', dir: 1, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }
];
public aggregations: ITreeGridAggregation[] = [
{
aggregate: (parent: any, data: any[]) => data.map((r) => r.change).reduce((ty, u) => ty + u, 0),
field: 'change'
},
{
aggregate: (parent: any, data: any[]) => data.map((r) => r.price).reduce((ty, u) => ty + u, 0),
field: 'price'
},
{
aggregate: (parent: any, data: any[]) => parent.change / (parent.price - parent.change) * 100,
field: 'changeP'
}
];
public childDataKey = 'children';
public groupColumnKey = 'categories';
public sorting = IgxGroupedTreeGridSorting.instance();
Angular Tree Grid Group By Load On Demand Example
Implementation
In this sample, data is loaded in portions. Initially, only the top level categories are displayed, then child data is served once a parent row is expanded. For more information on this approach, please refer to the Tree Grid Load On Demand topic. The data is grouped by the "ShipCountry", "ShipCity" and "Discontinued" fields and the resulting hierarchy is displayed in a separate column. The grouping is performed on a remote service - the data is modified and corresponding child and parent keys are assigned that are used to display the final data in a hierarchical view. For more information on how this service works you can take a look at the TreeGridGroupingLoadOnDemandService
class in the remoteService.ts
file.
Here is an example of how to use load on demand:
<igx-tree-grid #treeGrid
[data]="data"
[loadChildrenOnDemand]="loadChildren"
[primaryKey]="primaryKey"
[foreignKey]="foreignKey"
[hasChildrenKey]="hasChildrenKey">
<igx-tree-grid-group-by-area
[grid]="treeGrid"
[(expressions)]="groupingExpressions"
(expressionsChange)="onExpressionsChange($event)"
[hideGroupedColumns]="true">
</igx-tree-grid-group-by-area>
<igx-column [field]="groupColumnKey"></igx-column>
In order to load the child rows when the user expands a row, the Tree Grid provides the callback input property loadChildrenOnDemand
- the children data is retrieved from the server and it is assigned to the requested parent row based on the grouping parameters.
public groupingExpressions: IGroupingExpression[] = [
{ fieldName: 'ShipCountry', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance() },
{ fieldName: 'ShipCity', dir: 1, ignoreCase: true, strategy: DefaultSortingStrategy.instance() },
{ fieldName: 'Discontinued', dir: 1, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }
];
public primaryKey = 'id';
public foreignKey = 'parentId';
public hasChildrenKey = 'children';
public groupColumnKey = '';
private dataService = new TreeGridGroupingLoadOnDemandService();
public ngOnInit() {
this.reloadData();
}
public loadChildren = (parentID: any, done: (children: any[]) => void) => {
const groupingParameters = this.assembleGroupingParameters();
this.dataService.getData(parentID, this.hasChildrenKey, groupingParameters, (children) => done(children));
};
private reloadData() {
this.treeGrid.isLoading = true;
this.treeGrid.expansionStates.clear();
const groupingParameters = this.assembleGroupingParameters();
this.dataService.getData(null, this.hasChildrenKey, groupingParameters, (children) => {
this.data = children;
this.treeGrid.isLoading = false;
this.treeGrid.reflow();
});
}