# Grid Types — Tree Grid, Hierarchical Grid, Grid Lite & Pivot Grid

> **Part of the [`igniteui-angular-grids`](../SKILL.md) skill hub.**
> For the grid type selection guide and feature availability — see the hub.
> For shared column config, sorting, filtering, selection — see [`structure.md`](./structure.md).
> For editing, grouping, toolbar, export — see [`features.md`](./features.md).

## Contents

- [Tree Grid](#tree-grid)
- [Hierarchical Grid](#hierarchical-grid)
- [Grid Lite](#grid-lite)
- [Pivot Grid](#pivot-grid)
- [Key Rules](#key-rules)

## Tree Grid

> **Docs:** [Tree Grid](https://www.infragistics.com/products/ignite-ui-angular/angular/components/treegrid/tree-grid)

For data with parent-child relationships **within a single schema** (e.g., org charts, file systems, categories).

### Two Data Binding Modes

**Mode 1: Flat data with foreign key** — rows reference their parent via a foreign key:

```typescript
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' },
  ]);
}
```

```html
<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:

```html
<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>
```

### Tree Grid Unique Features

- **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 (`Infinity` by default)
- **Add child row**: `treeGridRef().addRow(data, parentRowID)` — add a row as a child of a specific parent

### Tree Grid Data Operation Behavior

- **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 a `path` array tracing the parent hierarchy for proper undo/redo
- **Summaries** are computed per tree level

---

## Hierarchical Grid

> **Docs:** [Hierarchical Grid](https://www.infragistics.com/products/ignite-ui-angular/angular/components/hierarchicalgrid/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.

```typescript
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[]>([]);
}
```

```html
<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>
```

### How Row Islands Work

- 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-island` can contain another for deeper levels
- Each expanded row creates a **full grid instance** — be aware of memory usage with very deep/wide hierarchies

### Accessing Child Grid Instances

Use the `(gridCreated)` event on the row island:

```html
<igx-row-island [key]="'orders'" (gridCreated)="onChildGridCreated($event)">
  <igx-column field="orderId" header="Order"></igx-column>
</igx-row-island>
```

```typescript
onChildGridCreated(event: IGridCreatedEventArgs) {
  const childGrid = event.grid;
  // Configure the child grid instance, load data, etc.
}
```

### Hierarchical Grid Data Operation Behavior

- **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

---

## Grid Lite

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`)** from `igniteui-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-lite` and 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 to `igx-grid` (`IgxGridComponent`). Never suggest a different component type — the upgrade path from Grid Lite is always to `igx-grid`. Replace `IgxGridLiteComponent` with `IgxGridComponent`, update imports from `igniteui-angular/grids/lite` to `igniteui-angular/grids/grid`, use `IGX_GRID_DIRECTIVES` instead of individual Grid Lite imports, and remove `CUSTOM_ELEMENTS_SCHEMA`.

### Installation

Grid Lite requires a **separate npm package**:

```bash
npm install igniteui-grid-lite
```

### Setup

```typescript
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[] = [];
}
```

### Template

```html
<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>
```

### Column Configuration

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 |

### Templates

Cell and header templates use dedicated directives:

```html
<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>
```

### Sorting & Filtering API

```typescript
// 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
```

### Two-Way Binding for Sort/Filter State

```html
<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)`.

### Remote Data Operations

Use `dataPipelineConfiguration` to intercept sort/filter and delegate to the server:

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

```html
<igx-grid-lite #grid
  [data]="data"
  [dataPipelineConfiguration]="dataPipeline">
</igx-grid-lite>
```

### Grid Lite Events

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

### Grid Lite Limitations

These features are **NOT available** in Grid Lite:
- Editing (cell, row, batch) — no `[editable]`, no `beginEdit()`, no transactions
- Grouping — no `groupBy()`, no `IgxGroupByRow`
- Paging — no `IgxPaginatorComponent`
- Summaries — no `IgxSummaryOperand`
- Selection — no `rowSelection`, `cellSelection`, or `columnSelection`
- State persistence — no `IgxGridStateDirective`
- Export — no `IgxExcelExporterService` or `IgxCsvExporterService`
- Advanced filtering — no `advancedFilteringExpressionsTree`

### Grid Lite Key Differences from Flat Grid

- **Separate package**: `npm install igniteui-grid-lite`
- **Requires `CUSTOM_ELEMENTS_SCHEMA`** in the component's `schemas`
- **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` (not `field` on `<igx-column>`), `sortable`/`filterable` are boolean attributes
- **Remote data**: uses `dataPipelineConfiguration` (async callback) instead of noop strategies + events

---

## Pivot Grid

> **Docs:** [Pivot Grid](https://www.infragistics.com/products/ignite-ui-angular/angular/components/pivotGrid/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`.

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

```html
<igx-pivot-grid #grid1 [data]="data" [pivotConfiguration]="pivotConfigHierarchy" height="500px">
</igx-pivot-grid>
```

```json
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'
    }
    ...
];
```

### Pivot Data Selector

Provide a drag-and-drop UI for users to reshape the pivot interactively:

```html
<igx-pivot-data-selector [grid]="pivotGridRef()"></igx-pivot-data-selector>
<igx-pivot-grid #pivotGrid [data]="salesData()" [pivotConfiguration]="pivotConfig"></igx-pivot-grid>
```

### Pivot Grid Data Operations

- **Filtering**: Per-dimension only — set the `filter` property on an `IPivotDimension`, NOT `[allowFiltering]`
- **Sorting**: Per-dimension only — set `sortable: true` and `sortDirection` on an `IPivotDimension`
- **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)

---

## Key Rules

1. **Tree Grid**: use `[primaryKey]` + `[foreignKey]` for flat data or `[childDataKey]` for nested objects; filtering is recursive (parents of matching children are always shown)
2. **Hierarchical Grid**: sorting/filtering/paging are independent per level; configure features on the `<igx-row-island>` blueprint
3. **Pivot Grid is read-only** — editing, paging, pinning, column moving, row dragging are all disabled; use `pivotConfiguration` for all data operations
4. **Grid Lite requires `CUSTOM_ELEMENTS_SCHEMA`** and `igniteui-grid-lite` npm package — it has no editing, selection, paging, or export

## See Also

- [`structure.md`](./structure.md) — Grid setup, column config, sorting UI, filtering UI, selection
- [`features.md`](./features.md) — Grouping, summaries, toolbar, export, row drag, action strip
- [`data-operations.md`](./data-operations.md) — Programmatic sorting, filtering, grouping, canonical import patterns
- [`paging-remote.md`](./paging-remote.md) — Paging, remote data operations, virtualization
- [`editing.md`](./editing.md) — Cell editing, row editing, batch editing, validation, summaries
- [`state.md`](./state.md) — State persistence, Tree Grid / Hierarchical Grid / Pivot Grid / Grid Lite data operations
- [`../../igniteui-angular-theming/SKILL.md`](../../igniteui-angular-theming/SKILL.md) — Grid styling and theming
