Part of the
igniteui-angular-gridsskill hub. For the grid type selection guide and feature availability — see the hub. For shared column config, sorting, filtering, selection — seestructure.md. For editing, grouping, toolbar, export — seefeatures.md.
Docs: Tree Grid
For data with parent-child relationships within a single schema (e.g., org charts, file systems, categories).
Mode 1: Flat data with foreign key — rows reference their parent via a foreign key:
import { Component, ChangeDetectionStrategy, signal, viewChild } from '@angular/core';
import { IgxTreeGridComponent, IGX_TREE_GRID_DIRECTIVES } from 'igniteui-angular/grids/tree-grid';
@Component({
selector: 'app-org-tree',
imports: [IGX_TREE_GRID_DIRECTIVES],
templateUrl: './org-tree.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class OrgTreeComponent {
treeGridRef = viewChild.required<IgxTreeGridComponent>('treeGrid');
employees = signal<Employee[]>([
{ id: 1, name: 'CEO', managerId: -1, title: 'CEO' },
{ id: 2, name: 'VP Engineering', managerId: 1, title: 'VP' },
{ id: 3, name: 'Developer', managerId: 2, title: 'Dev' },
]);
}<igx-tree-grid #treeGrid
[data]="employees()"
[primaryKey]="'id'"
[foreignKey]="'managerId'"
[autoGenerate]="false"
[rowSelection]="'multipleCascade'"
height="600px">
<igx-column field="name" header="Name" [sortable]="true"></igx-column>
<igx-column field="title" header="Title"></igx-column>
</igx-tree-grid>Mode 2: Nested object data — each row contains its children in an array property:
<igx-tree-grid #treeGrid
[data]="departments()"
[primaryKey]="'id'"
[childDataKey]="'children'"
[autoGenerate]="false"
height="600px">
<igx-column field="name" header="Name"></igx-column>
<igx-column field="headCount" header="Employees" dataType="number"></igx-column>
</igx-tree-grid>- Cascade selection:
[rowSelection]="'multipleCascade'"— selecting a parent selects all children; indeterminate state propagates up - Cascade delete:
[cascadeOnDelete]="true"(default) — deleting a parent removes all descendants - Load on demand:
[loadChildrenOnDemand]="loadChildren"— lazy-load children when a row is expanded - Expansion depth:
[expansionDepth]="2"— control initial expansion level (Infinityby default) - Add child row:
treeGridRef().addRow(data, parentRowID)— add a row as a child of a specific parent
- Filtering is recursive: when a child matches, its parent is always shown (even if the parent doesn't match). Matched parents are auto-expanded.
- Sorting is per-level: children are sorted within their parent, not globally flattened
- Batch editing uses
HierarchicalTransactionService— transactions carry apatharray tracing the parent hierarchy for proper undo/redo - Summaries are computed per tree level
Docs: Hierarchical Grid
For master-detail data where each level has a different schema (e.g., Companies → Departments → Employees). Each level is defined by a Row Island blueprint.
import { Component, ChangeDetectionStrategy, signal, viewChild } from '@angular/core';
import { IgxHierarchicalGridComponent, IGX_HIERARCHICAL_GRID_DIRECTIVES } from 'igniteui-angular/grids/hierarchical-grid';
@Component({
selector: 'app-company-grid',
imports: [IGX_HIERARCHICAL_GRID_DIRECTIVES],
templateUrl: './company-grid.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CompanyGridComponent {
hGridRef = viewChild.required<IgxHierarchicalGridComponent>('hGrid');
companies = signal<Company[]>([]);
}<igx-hierarchical-grid #hGrid
[data]="companies()"
[primaryKey]="'id'"
[autoGenerate]="false"
height="600px">
<igx-column field="name" header="Company"></igx-column>
<igx-column field="industry" header="Industry"></igx-column>
<igx-row-island [key]="'departments'" [autoGenerate]="false" [primaryKey]="'deptId'">
<igx-column field="name" header="Department"></igx-column>
<igx-column field="headCount" header="Employees" dataType="number"></igx-column>
<igx-row-island [key]="'employees'" [autoGenerate]="false" [primaryKey]="'empId'">
<igx-column field="name" header="Name"></igx-column>
<igx-column field="role" header="Role"></igx-column>
</igx-row-island>
</igx-row-island>
</igx-hierarchical-grid>- A
<igx-row-island>defines the blueprint (columns, features, templates) for all child grids at that level - The
[key]property specifies which property of the parent row's data holds the child array - Row islands can be nested — an
igx-row-islandcan contain another for deeper levels - Each expanded row creates a full grid instance — be aware of memory usage with very deep/wide hierarchies
Use the (gridCreated) event on the row island:
<igx-row-island [key]="'orders'" (gridCreated)="onChildGridCreated($event)">
<igx-column field="orderId" header="Order"></igx-column>
</igx-row-island>onChildGridCreated(event: IGridCreatedEventArgs) {
const childGrid = event.grid;
// Configure the child grid instance, load data, etc.
}- Sorting and filtering do NOT cascade — each grid level is independent with its own state
- Configure features on the row island and all child grids at that level inherit them
- Batch editing propagates: setting
[batchEditing]="true"on the root automatically enables it on all child grids - State persistence recursively saves/restores state for each child grid instance, keyed by row island ID + parent row ID
The lightest grid option — an open-source (MIT licensed) Web Component with an Angular wrapper. Use it for read-only data display with sorting, filtering, column hiding/resizing, and row virtualization. It has no editing, no selection, no paging, no grouping, no summaries, no export.
When to recommend Grid Lite vs. Flat Grid: If the user only needs to display data with basic sorting/filtering and doesn't need editing, batch operations, paging, grouping, summaries, or export, Grid Lite is the lighter, faster choice. If any of those enterprise features are needed, upgrade strictly to
igx-grid(IgxGridComponent) fromigniteui-angular/grids/grid— do NOT recommend other non-grid components as a substitute.
AGENT INSTRUCTION — Grid Lite → Grid Upgrade: When a user is working with
igx-grid-liteand you identify that their requirements exceed Grid Lite's capabilities (e.g., they need editing, selection, paging, grouping, summaries, export, row operations, or any feature not available in Grid Lite), you MUST recommend upgrading toigx-grid(IgxGridComponent). Never suggest a different component type — the upgrade path from Grid Lite is always toigx-grid. ReplaceIgxGridLiteComponentwithIgxGridComponent, update imports fromigniteui-angular/grids/litetoigniteui-angular/grids/grid, useIGX_GRID_DIRECTIVESinstead of individual Grid Lite imports, and removeCUSTOM_ELEMENTS_SCHEMA.
Grid Lite requires a separate npm package:
npm install igniteui-grid-liteimport { Component, CUSTOM_ELEMENTS_SCHEMA, viewChild } from '@angular/core';
import {
IgxGridLiteComponent,
IgxGridLiteColumnComponent,
IgxGridLiteCellTemplateDirective,
IgxGridLiteHeaderTemplateDirective
} from 'igniteui-angular/grids/lite';
@Component({
selector: 'app-users-lite',
imports: [
IgxGridLiteComponent,
IgxGridLiteColumnComponent,
IgxGridLiteCellTemplateDirective,
IgxGridLiteHeaderTemplateDirective
],
schemas: [CUSTOM_ELEMENTS_SCHEMA], // Required — Grid Lite is a Web Component
templateUrl: './users-lite.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UsersLiteComponent {
gridRef = viewChild<IgxGridLiteComponent<User>>('grid');
data: User[] = [];
}<igx-grid-lite #grid
[data]="data"
[autoGenerate]="false"
[sortingOptions]="{ mode: 'multiple' }">
<igx-grid-lite-column
field="name"
dataType="string"
header="Name"
sortable
filterable
resizable>
</igx-grid-lite-column>
<igx-grid-lite-column
field="age"
dataType="number"
header="Age"
sortable
filterable>
</igx-grid-lite-column>
<igx-grid-lite-column field="active" dataType="boolean" header="Active">
<ng-template igxGridLiteCell let-value>
<span>{{ value ? 'Yes' : 'No' }}</span>
</ng-template>
</igx-grid-lite-column>
</igx-grid-lite>Columns use <igx-grid-lite-column> with these inputs:
| Input | Type | Description |
|---|---|---|
field |
string |
Data property key (required) |
dataType |
'string' | 'number' | 'boolean' | 'date' |
Column data type |
header |
string |
Header text |
width |
string |
CSS width (e.g., '250px') |
hidden |
boolean |
Hide the column |
resizable |
boolean |
Allow column resizing |
sortable |
boolean |
Enable sorting |
filterable |
boolean |
Enable filtering |
sortingCaseSensitive |
boolean |
Case-sensitive sorting |
filteringCaseSensitive |
boolean |
Case-sensitive filtering |
Cell and header templates use dedicated directives:
<igx-grid-lite-column field="status" header="Status">
<!-- Custom cell template -->
<ng-template igxGridLiteCell let-value let-row="row" let-column="column">
<span [class]="value">{{ value }}</span>
</ng-template>
<!-- Custom header template -->
<ng-template igxGridLiteHeader let-column>
<strong>{{ column.header }}</strong>
</ng-template>
</igx-grid-lite-column>// Sort programmatically
this.gridRef().sort({ key: 'name', direction: 'ascending' });
this.gridRef().sort([
{ key: 'name', direction: 'ascending' },
{ key: 'age', direction: 'descending' }
]);
this.gridRef().clearSort('name');
this.gridRef().clearSort(); // clear all
// Filter programmatically
this.gridRef().filter({ key: 'age', condition: 'greaterThan', searchTerm: 21 });
this.gridRef().clearFilter('age');
this.gridRef().clearFilter(); // clear all<igx-grid-lite #grid
[data]="data"
[(sortingExpressions)]="sortExprs"
[(filteringExpressions)]="filterExprs"
(sorting)="onSorting($event)"
(sorted)="onSorted($event)"
(filtering)="onFiltering($event)"
(filtered)="onFiltered($event)">
</igx-grid-lite>Events: (sorting) (cancelable), (sorted), (filtering) (cancelable), (filtered).
Use dataPipelineConfiguration to intercept sort/filter and delegate to the server:
import { IgxGridLiteDataPipelineConfiguration } from 'igniteui-angular/grids/lite';
dataPipeline: IgxGridLiteDataPipelineConfiguration<Product> = {
sort: async (params) => {
// params.grid — the grid instance
// params.data — current data
// params.type — 'sort'
const sorted = await this.dataService.sortRemote(params.grid.sortingExpressions);
return sorted;
},
filter: async (params) => {
const filtered = await this.dataService.filterRemote(params.grid.filteringExpressions);
return filtered;
}
};<igx-grid-lite #grid
[data]="data"
[dataPipelineConfiguration]="dataPipeline">
</igx-grid-lite>| Event | Cancelable | Payload |
|---|---|---|
(sorting) |
Yes (event.detail.cancel = true) |
Sorting expression about to be applied |
(sorted) |
No | Sorting completed |
(filtering) |
Yes (event.detail.cancel = true) |
Filter expression about to be applied |
(filtered) |
No | Filtering completed |
These features are NOT available in Grid Lite:
- Editing (cell, row, batch) — no
[editable], nobeginEdit(), no transactions - Grouping — no
groupBy(), noIgxGroupByRow - Paging — no
IgxPaginatorComponent - Summaries — no
IgxSummaryOperand - Selection — no
rowSelection,cellSelection, orcolumnSelection - State persistence — no
IgxGridStateDirective - Export — no
IgxExcelExporterServiceorIgxCsvExporterService - Advanced filtering — no
advancedFilteringExpressionsTree
- Separate package:
npm install igniteui-grid-lite - Requires
CUSTOM_ELEMENTS_SCHEMAin the component'sschemas - No directives bundle — import
IgxGridLiteComponent,IgxGridLiteColumnComponent, and template directives individually - No
[primaryKey]— not needed (no editing, selection, or row operations) - No editing of any kind (cell, row, batch)
- No selection (row, cell, column)
- No paging, grouping, summaries, pinning, moving, export
- Column config differs: uses
field(notfieldon<igx-column>),sortable/filterableare boolean attributes - Remote data: uses
dataPipelineConfiguration(async callback) instead of noop strategies + events
Docs: Pivot Grid
For pivot table analytics where users reshape data by dragging dimensions between rows, columns, filters, and values.
IMPORTANT: The Pivot Grid is fundamentally different from the other three grids. Standard grid features like cell editing, row editing, batch editing, paging, column pinning, column moving, row dragging, and standard filtering/sorting are disabled. All data operations are driven by the
pivotConfiguration.
import { Component } from "@angular/core";
import { DATA } from '../../data/pivot-data';
import { IPivotConfiguration, IgxPivotNumericAggregate } from 'igniteui-angular/grids/core';
import { IgxPivotGridComponent } from 'igniteui-angular/grids/pivot-grid';
@Component({
selector: 'app-pivot-grid-basic-sample',
styleUrls: ['./pivot-grid-basic-sample.component.scss'],
templateUrl: './pivot-grid-basic-sample.component.html',
imports: [IgxPivotGridComponent]
})
export class PivotGridBasicSampleComponent {
public data = DATA;
public pivotConfigHierarchy: IPivotConfiguration = {
columns: [
{
memberName: 'Product',
memberFunction: (data) => data.Product.Name,
enabled: true
}
],
rows: [
{
memberName: 'Seller',
memberFunction: (data) => data.Seller.Name,
enabled: true
}
],
values: [
{
member: 'NumberOfUnits',
aggregate: {
aggregator: IgxPivotNumericAggregate.sum,
key: 'sum',
label: 'Sum'
},
enabled: true
}
],
filters: null
};
}<igx-pivot-grid #grid1 [data]="data" [pivotConfiguration]="pivotConfigHierarchy" height="500px">
</igx-pivot-grid>export const DATA = [
{
Product: {
Name: 'Clothing',
UnitPrice: '12.814860936633712'
},
Seller: {
Name: 'Stanley Brooker',
City: 'Seattle'
},
Date: '2007-01-01T00:00:00',
Value: '94.2652032683907',
NumberOfUnits: '282'
},
{
Product: {
Name: 'Clothing',
UnitPrice: '49.579375120615296'
},
Seller: {
Name: 'Elisa Longbottom',
City: 'Sofia'
},
Date: '2007-01-05T00:00:00',
Value: '70.798922689072285',
NumberOfUnits: '296'
}
...
];Provide a drag-and-drop UI for users to reshape the pivot interactively:
<igx-pivot-data-selector [grid]="pivotGridRef()"></igx-pivot-data-selector>
<igx-pivot-grid #pivotGrid [data]="salesData()" [pivotConfiguration]="pivotConfig"></igx-pivot-grid>- Filtering: Per-dimension only — set the
filterproperty on anIPivotDimension, NOT[allowFiltering] - Sorting: Per-dimension only — set
sortable: trueandsortDirectionon anIPivotDimension - Aggregation: Configured via
IPivotValue.aggregate(e.g.,IgxPivotNumericAggregate.sum,.average,.min,.max,.count) - Columns are auto-generated from the pivot configuration — do not define
<igx-column>manually - State persistence: Serializes the entire
pivotConfiguration(dimensions, values, filters)
- Tree Grid: use
[primaryKey]+[foreignKey]for flat data or[childDataKey]for nested objects; filtering is recursive (parents of matching children are always shown) - Hierarchical Grid: sorting/filtering/paging are independent per level; configure features on the
<igx-row-island>blueprint - Pivot Grid is read-only — editing, paging, pinning, column moving, row dragging are all disabled; use
pivotConfigurationfor all data operations - Grid Lite requires
CUSTOM_ELEMENTS_SCHEMAandigniteui-grid-litenpm package — it has no editing, selection, paging, or export
structure.md— Grid setup, column config, sorting UI, filtering UI, selectionfeatures.md— Grouping, summaries, toolbar, export, row drag, action stripdata-operations.md— Programmatic sorting, filtering, grouping, canonical import patternspaging-remote.md— Paging, remote data operations, virtualizationediting.md— Cell editing, row editing, batch editing, validation, summariesstate.md— State persistence, Tree Grid / Hierarchical Grid / Pivot Grid / Grid Lite data operations../../igniteui-angular-theming/SKILL.md— Grid styling and theming