Build data-rich Angular apps with Ignite UI Grid, Tree Grid, Hierarchical Grid, and Pivot Grid
This skill teaches AI agents how to build rich data grid experiences with Ignite UI for Angular. It covers the four grid types (Grid, Tree Grid, Hierarchical Grid, Pivot Grid), column configuration, sorting, filtering, editing, selection, grouping, summaries, export, and advanced features like batch editing, cell merging, multi-row layouts, and virtualization.
Related Skill: Grid Data Operations & State Management
This skill focuses on grid structure — choosing a grid type, configuring columns, templates, layout, selection, toolbar, and export. For data manipulation patterns — remote data binding, programmatic sorting/filtering/grouping, paging, batch editing workflows, state persistence, and wiring up services — see the dedicated skill.
igniteui-angular-grid-data-operationsIf the user's question is about what to render, use this skill. If it's about how data flows, use the Data Operations skill.
igniteui-angular installed, or @infragistics/igniteui-angular for licensed users — both packages share the same entry-point structureIgnite UI has five grid types. Picking the correct one is the most important decision — each has different data structures, features, and constraints.
Ask these questions in order:
managerId field, or nested children arrays)? → Tree GridEntry points below use the igniteui-angular prefix. Replace with @infragistics/igniteui-angular for the licensed package.
| Grid | Selector | Component | Directives | Entry Point | Docs |
|---|---|---|---|---|---|
| Grid Lite | igx-grid-lite | IgxGridLiteComponent | Individual imports | igniteui-angular/grids/lite | — |
| Flat Grid | igx-grid | IgxGridComponent | IGX_GRID_DIRECTIVES | igniteui-angular/grids/grid | Docs |
| Tree Grid | igx-tree-grid | IgxTreeGridComponent | IGX_TREE_GRID_DIRECTIVES | igniteui-angular/grids/tree-grid | Docs |
| Hierarchical Grid | igx-hierarchical-grid | IgxHierarchicalGridComponent | IGX_HIERARCHICAL_GRID_DIRECTIVES | igniteui-angular/grids/hierarchical-grid | Docs |
| Pivot Grid | igx-pivot-grid | IgxPivotGridComponent | IGX_PIVOT_GRID_DIRECTIVES | igniteui-angular/grids/pivot-grid | Docs |
AGENT INSTRUCTION — Documentation URL Pattern: For grid-specific topics (sorting, filtering, editing, paging, etc.), docs URLs follow this naming pattern per grid type:
- Flat Grid:
.../components/grid/{topic}- Tree Grid:
.../components/treegrid/{topic}- Hierarchical Grid:
.../components/hierarchicalgrid/{topic}- Pivot Grid:
.../components/pivotGrid/{topic}Example: the sorting topic is
/grid/sorting,/treegrid/sorting,/hierarchicalgrid/sorting,/pivotGrid/sorting. Docs links in the sections below use the Flat Grid URL; substitute the prefix above for the other grid types.
| Feature | Grid Lite | Flat Grid | Tree Grid | Hierarchical Grid | Pivot Grid |
|---|---|---|---|---|---|
| Column sorting | Yes | Yes | Yes (per-level) | Yes (per grid level) | Per-dimension only |
| Column filtering | Yes | Yes | Yes (recursive — keeps matching parents) | Yes (per grid level) | Per-dimension only |
| GroupBy | No | Exclusive | No (use tree hierarchy) | No | Inherent via dimensions |
| Paging | No | Yes | Yes | Yes (each level independent) | No |
| Batch editing | No | Yes | Yes (hierarchical transactions) | Yes (propagated from root) | No |
| Cell / Row editing | No | Yes | Yes | Yes (per grid level) | No |
| Row adding | No | Yes | Yes (with parent support) | Yes (per grid level) | No |
| Master-Detail | No | Exclusive | No | No (use row islands) | No |
| Row selection | No | Yes | Yes + multipleCascade | Yes (per grid level) | Limited |
| Load on demand | No | No | Exclusive | No | No |
| Column pinning / moving | No | Yes | Yes | Yes | No |
| Column hiding | Yes | Yes | Yes | Yes | No |
| Column resizing | Yes | Yes | Yes | Yes | No |
| Summaries | No | Yes | Yes (per-level) | Yes (per grid level) | Horizontal summaries only |
| State persistence | No | Yes | Yes | Yes + row island state | Pivot config serialization |
| Remote data ops | dataPipelineConfiguration | Events + noop strategies | Events + noop strategies | Events + noop strategies | N/A |
| Row virtualization | Yes | Yes (rows + columns) | Yes (rows + columns) | Yes (rows + columns) | Yes |
Docs: Flat Grid · Tree Grid · Hierarchical Grid · Pivot Grid
AGENT INSTRUCTION: Check
package.jsonto determine whether the project usesigniteui-angularor@infragistics/igniteui-angular. Always import from the specific entry point of whichever package is installed. Never import from the root barrel of either package.
// Open-source package — import from specific entry points
import { IgxGridComponent, IGX_GRID_DIRECTIVES } from 'igniteui-angular/grids/grid';
// Licensed package — same entry-point structure, different prefix
// import { IgxGridComponent, IGX_GRID_DIRECTIVES } from '@infragistics/igniteui-angular/grids/grid';
// AVOID — never import from the root barrel (wrong for BOTH variants)
// import { IgxGridComponent } from 'igniteui-angular';
// import { IgxGridComponent } from '@infragistics/igniteui-angular';
import { Component, ChangeDetectionStrategy, signal, viewChild } from '@angular/core';
@Component({
selector: 'app-users-grid',
imports: [IGX_GRID_DIRECTIVES],
templateUrl: './users-grid.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UsersGridComponent {
// Signal-based view child — use #grid on the template element
gridRef = viewChild.required<IgxGridComponent>('grid');
protected users = signal<User[]>([]);
}
<igx-grid #grid
[data]="users()"
[primaryKey]="'id'"
[autoGenerate]="false"
height="600px"
width="100%">
<igx-column field="id" header="ID" [hidden]="true"></igx-column>
<igx-column field="name" header="Name" [sortable]="true" [filterable]="true" [resizable]="true"></igx-column>
<igx-column field="email" header="Email" [sortable]="true" [filterable]="true"></igx-column>
<igx-column field="role" header="Role" [groupable]="true" [filterable]="true"></igx-column>
<igx-column field="salary" header="Salary" dataType="number" [hasSummary]="true"></igx-column>
<igx-column field="hireDate" header="Hire Date" dataType="date" [sortable]="true"></igx-column>
<igx-column field="active" header="Active" dataType="boolean"></igx-column>
</igx-grid>
Docs: Column Types
Set dataType to enable proper formatting, filtering, sorting, and editing:
| dataType | Behavior |
|---|---|
string | Text input, string filtering |
number | Numeric input, number filtering, number summaries |
boolean | Checkbox editor, boolean filtering |
date | Date picker editor, date filtering |
dateTime | Date+time editor |
time | Time picker editor |
currency | Currency formatting, number filtering |
percent | Percentage formatting |
image | Image rendering (read-only) |
Docs: Column Configuration
Override default rendering with template directives:
<igx-column field="status" header="Status">
<!-- Custom cell template -->
<ng-template igxCell let-cell="cell">
<igx-badge [type]="cell.value === 'Active' ? 'success' : 'error'">
{{ cell.value }}
</igx-badge>
</ng-template>
<!-- Custom header template -->
<ng-template igxHeader let-column>
<igx-icon>verified</igx-icon> {{ column.header }}
</ng-template>
<!-- Custom editor template -->
<ng-template igxCellEditor let-cell="cell">
<igx-select [(ngModel)]="cell.editValue">
<igx-select-item value="Active">Active</igx-select-item>
<igx-select-item value="Inactive">Inactive</igx-select-item>
</igx-select>
</ng-template>
<!-- Custom filter cell template -->
<ng-template igxFilterCellTemplate let-column="column">
<input (input)="onCustomFilter($event, column)" />
</ng-template>
<!-- Custom summary template -->
<ng-template igxSummary let-summaryResults>
Active: {{ getActiveCount(summaryResults) }}
</ng-template>
</igx-column>
Group columns under a shared header:
<igx-column-group header="Personal Info">
<igx-column field="firstName" header="First Name"></igx-column>
<igx-column field="lastName" header="Last Name"></igx-column>
</igx-column-group>
<igx-column-group header="Contact">
<igx-column field="email" header="Email"></igx-column>
<igx-column field="phone" header="Phone"></igx-column>
</igx-column-group>
Docs: Multi-Row Layout
Create complex cell layouts spanning multiple rows/columns:
<igx-column-layout>
<igx-column field="name" [rowStart]="1" [colStart]="1" [colEnd]="3"></igx-column>
<igx-column field="email" [rowStart]="2" [colStart]="1"></igx-column>
<igx-column field="phone" [rowStart]="2" [colStart]="2"></igx-column>
</igx-column-layout>
Docs: Column Pinning
<igx-column field="name" [pinned]="true"></igx-column>
Or programmatically: this.gridRef().pinColumn('name').
Docs: Sorting (substitute URL prefix per grid type — see instruction above)
<igx-grid
[data]="data()"
[(sortingExpressions)]="sortExprs"
[sortingOptions]="{ mode: 'multiple' }">
<igx-column field="name" [sortable]="true"></igx-column>
</igx-grid>
Programmatic sorting:
this.gridRef().sort({ fieldName: 'name', dir: SortingDirection.Asc, ignoreCase: true });
this.gridRef().clearSort();
Events: (sorting) (cancelable), (sortingDone).
Docs: Filtering
<igx-grid [allowFiltering]="true" [filterMode]="'quickFilter'">
<igx-column field="name" [filterable]="true"></igx-column>
</igx-grid>
Docs: Excel-Style Filtering
<igx-grid [allowFiltering]="true" [filterMode]="'excelStyleFilter']">
<igx-column field="name" [filterable]="true"></igx-column>
</igx-grid>
Docs: Advanced Filtering
<igx-grid [allowAdvancedFiltering]="true">
<!-- Advanced filtering UI is shown via toolbar or API -->
</igx-grid>
this.gridRef().filter('name', 'John', IgxStringFilteringOperand.instance().condition('contains'), true);
this.gridRef().clearFilter('name');
this.gridRef().clearFilter(); // clear all
Events: (filtering) (cancelable), (filteringDone).
Docs: Row Selection
<igx-grid [rowSelection]="'multiple'" [primaryKey]="'id'" [(selectedRows)]="selectedIds">
<!-- Optional: Custom row selector checkbox -->
<ng-template igxRowSelector let-rowContext>
<igx-checkbox [checked]="rowContext.selected" (change)="rowContext.select(!rowContext.selected)">
</igx-checkbox>
</ng-template>
</igx-grid>
Modes: 'none', 'single', 'multiple', 'multipleCascade' (tree grids).
Docs: Cell Selection
<igx-grid [cellSelection]="'multiple'"></igx-grid>
Docs: Column Selection
<igx-grid [columnSelection]="'multiple'">
<igx-column field="name" [selectable]="true"></igx-column>
</igx-grid>
Events: (rowSelectionChanging), (columnSelectionChanging), (selected) (cell).
Docs: Cell Editing
<igx-column field="name" [editable]="true"></igx-column>
Double-click or press Enter to enter edit mode. Events: (cellEditEnter), (cellEdit) (cancelable), (cellEditDone), (cellEditExit).
Docs: Row Editing
<igx-grid [rowEditable]="true" [primaryKey]="'id'">
<!-- Custom row edit overlay text -->
<ng-template igxRowEditText let-rowChanges>
{{ rowChanges.size }} fields changed
</ng-template>
<ng-template igxRowEditActions>
<button igxButton="flat" igxRowEditTabStop (click)="rowEditCtx.endRowEdit(false)">Cancel</button>
<button igxButton="flat" igxRowEditTabStop (click)="rowEditCtx.endRowEdit(true)">Save</button>
</ng-template>
</igx-grid>
Events: (rowEditEnter), (rowEdit) (cancelable), (rowEditDone), (rowEditExit).
Docs: Batch Editing
<igx-grid [batchEditing]="true" [primaryKey]="'id'" [rowEditable]="true"></igx-grid>
// Commit all changes
this.gridRef().transactions.commit(this.gridRef().data);
// Undo last change
this.gridRef().transactions.undo();
// Redo
this.gridRef().transactions.redo();
// Discard all changes
this.gridRef().transactions.clear();
Docs: Row Adding
// Add row
this.gridRef().addRow({ id: 999, name: 'New User', email: '[email protected]' });
// Delete row by primary key
this.gridRef().deleteRow(42);
// Open add-row UI at top or bottom
this.gridRef().beginAddRowByIndex(0); // at top
Events: (rowAdded), (rowDeleted), (rowAdd) (cancelable), (rowDelete) (cancelable).
Docs: Validation
Built-in validators on columns:
<igx-column field="email" [editable]="true" required [validators]="emailValidators">
</igx-column>
emailValidators = [Validators.required, Validators.email];
Events: (formGroupCreated), (validationStatusChange).
Docs: Group By
<igx-grid [data]="data()" [groupsExpanded]="true">
<igx-column field="category" [groupable]="true"></igx-column>
<!-- Custom group row template -->
<ng-template igxGroupByRow let-groupRow>
{{ groupRow.expression.fieldName }}: {{ groupRow.value }} ({{ groupRow.records.length }} items)
</ng-template>
</igx-grid>
Programmatic:
this.gridRef().groupBy({ fieldName: 'category', dir: SortingDirection.Asc });
this.gridRef().clearGrouping('category');
Docs: Summaries (substitute URL prefix per grid type — see instruction above)
Enable per-column summaries:
<igx-column field="salary" dataType="number" [hasSummary]="true"></igx-column>
Default summaries by type:
Custom summary class:
class SalarySummary extends IgxNumberSummaryOperand {
operate(data: number[]): IgxSummaryResult[] {
return [{
key: 'median',
label: 'Median',
summaryResult: this.median(data)
}];
}
private median(data: number[]): number {
const sorted = [...data].sort((a, b) => a - b);
const mid = Math.floor(sorted.length / 2);
return sorted.length % 2 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
}
}
<igx-column field="salary" [hasSummary]="true" [summaries]="salarySummary">
</igx-column>
Merge adjacent cells with equal values:
<igx-column field="category" [merge]="true"></igx-column>
Or apply a custom merge strategy:
<igx-column field="price" [merge]="true" [mergeStrategy]="priceRangeMerge"></igx-column>
priceRangeMerge: IgxCellMergeStrategy = {
shouldMerge(prevCell, curCell) {
return Math.abs(prevCell.value - curCell.value) < 10;
}
};
Docs: Toolbar
<igx-grid [data]="data()">
<igx-grid-toolbar>
<igx-grid-toolbar-title>Products</igx-grid-toolbar-title>
<igx-grid-toolbar-actions>
<igx-grid-toolbar-hiding></igx-grid-toolbar-hiding>
<igx-grid-toolbar-pinning></igx-grid-toolbar-pinning>
<igx-grid-toolbar-exporter></igx-grid-toolbar-exporter>
<igx-grid-toolbar-advanced-filtering></igx-grid-toolbar-advanced-filtering>
</igx-grid-toolbar-actions>
</igx-grid-toolbar>
<igx-column field="name"></igx-column>
</igx-grid>
Docs: Excel Export
import { IgxExcelExporterService, IgxExcelExporterOptions } from 'igniteui-angular/grids/core';
export class MyComponent {
private excelExporter = inject(IgxExcelExporterService);
exportToExcel() {
this.excelExporter.exportData(this.data(), new IgxExcelExporterOptions('export'));
// Or export the grid (respects filtering/sorting)
this.excelExporter.export(this.grid, new IgxExcelExporterOptions('export'));
}
}
Docs: CSV Export
import { IgxCsvExporterService, IgxCsvExporterOptions, CsvFileTypes } from 'igniteui-angular/grids/core';
export class MyComponent {
private csvExporter = inject(IgxCsvExporterService);
exportToCsv() {
this.csvExporter.export(this.grid, new IgxCsvExporterOptions('export', CsvFileTypes.CSV));
}
}
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>
[rowSelection]="'multipleCascade'" — selecting a parent selects all children; indeterminate state propagates up[cascadeOnDelete]="true" (default) — deleting a parent removes all descendants[loadChildrenOnDemand]="loadChildren" — lazy-load children when a row is expanded[expansionDepth]="2" — control initial expansion level (Infinity by default)treeGridRef().addRow(data, parentRowID) — add a row as a child of a specific parentHierarchicalTransactionService — transactions carry a path array tracing the parent hierarchy for proper undo/redoDocs: 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>
<igx-row-island> defines the blueprint (columns, features, templates) for all child grids at that level[key] property specifies which property of the parent row's data holds the child arrayigx-row-island can contain another for deeper levelsUse 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.
}
[batchEditing]="true" on the root automatically enables it on all child gridsThe 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, use the Flat Grid.
Grid Lite requires a separate npm package:
npm install igniteui-grid-lite
import { 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>
npm install igniteui-grid-liteCUSTOM_ELEMENTS_SCHEMA in the component's schemasIgxGridLiteComponent, IgxGridLiteColumnComponent, and template directives individually[primaryKey] — not needed (no editing, selection, or row operations)field (not field on <igx-column>), sortable/filterable are boolean attributesdataPipelineConfiguration (async callback) instead of noop strategies + eventsDocs: 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, ChangeDetectionStrategy, signal, viewChild } from '@angular/core';
import { IgxPivotGridComponent, IGX_PIVOT_GRID_DIRECTIVES } from 'igniteui-angular/grids/pivot-grid';
import { IPivotConfiguration, IgxPivotNumericAggregate } from 'igniteui-angular/grids/pivot-grid';
@Component({
selector: 'app-sales-pivot',
imports: [IGX_PIVOT_GRID_DIRECTIVES],
templateUrl: './sales-pivot.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SalesPivotComponent {
pivotGridRef = viewChild.required<IgxPivotGridComponent>('pivotGrid');
salesData = signal<Sale[]>([]);
pivotConfig: IPivotConfiguration = {
columns: [{ memberName: 'Quarter', enabled: true }],
rows: [{ memberName: 'Region', enabled: true }],
values: [{
member: 'Revenue',
aggregate: { aggregator: IgxPivotNumericAggregate.sum, key: 'SUM', label: 'Sum' },
enabled: true
}],
filters: [{ memberName: 'Year', enabled: true }]
};
}
<igx-pivot-grid #pivotGrid
[data]="salesData()"
[pivotConfiguration]="pivotConfig"
height="600px">
</igx-pivot-grid>
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>
filter property on an IPivotDimension, NOT [allowFiltering]sortable: true and sortDirection on an IPivotDimensionIPivotValue.aggregate (e.g., IgxPivotNumericAggregate.sum, .average, .min, .max, .count)<igx-column> manuallypivotConfiguration (dimensions, values, filters)Docs: Virtualization
Grids use virtualization by default for both rows and columns — no setup needed. For remote data/paging:
<igx-grid [data]="data()" [totalItemCount]="totalCount" (dataPreLoad)="onDataPreLoad($event)">
</igx-grid>
Docs: Row Drag
<igx-grid [rowDraggable]="true" (rowDragStart)="onDragStart($event)" (rowDragEnd)="onDragEnd($event)">
<ng-template igxRowDragGhost let-dragData>
<span>Moving {{ dragData.dragData.name }}</span>
</ng-template>
</igx-grid>
Docs: Action Strip
Overlay actions on a row:
<igx-grid [data]="data()">
<igx-action-strip>
<igx-grid-editing-actions [addRow]="true"></igx-grid-editing-actions>
<igx-grid-pinning-actions></igx-grid-pinning-actions>
</igx-action-strip>
<igx-column field="name"></igx-column>
</igx-grid>
Docs: Master-Detail
Expand rows to show arbitrary detail content:
<igx-grid [data]="orders()" [primaryKey]="'orderId'">
<igx-column field="orderId"></igx-column>
<igx-column field="customer"></igx-column>
<ng-template igxGridDetail let-dataItem>
<div class="detail-container">
<h4>Order Items for {{ dataItem.customer }}</h4>
<igx-grid [data]="dataItem.items" [autoGenerate]="true" height="200px">
</igx-grid>
</div>
</ng-template>
</igx-grid>
Grids support copy to clipboard by default. Configure via:
<igx-grid [clipboardOptions]="{ enabled: true, copyHeaders: true, copyFormatters: true, separator: '\t' }">
</igx-grid>
[primaryKey] — required for editing, selection, row operations (Flat, Tree, Hierarchical, Pivot grids; NOT Grid Lite)IGX_GRID_DIRECTIVES, IGX_TREE_GRID_DIRECTIVES, IGX_HIERARCHICAL_GRID_DIRECTIVES, IGX_PIVOT_GRID_DIRECTIVES, or individual Grid Lite importsviewChild — IgxGridLiteComponent, IgxGridComponent, IgxTreeGridComponent, IgxHierarchicalGridComponent, or IgxPivotGridComponent[autoGenerate]="false" and define columns explicitly for production grids (except Pivot Grid where columns are auto-generated)dataType on every column for correct filtering, sorting, editing, and summariesevent.cancel = true in (rowEdit), (cellEdit), (sorting), (filtering) to prevent the action[data]="myData()" with signal<T[]>([])CUSTOM_ELEMENTS_SCHEMA and igniteui-grid-lite npm package — it has no editing, selection, paging, or export[primaryKey] + [foreignKey] for flat data or [childDataKey] for nested objects; filtering is recursive (parents of matching children are always shown)<igx-row-island> blueprintpivotConfiguration for all data operations