@igniteui/angular-templates 21.1.14100-alpha.2 → 21.1.14100-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/SKILL.md +68 -0
  2. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/charts.md +457 -0
  3. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/data-display.md +360 -0
  4. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/directives.md +272 -0
  5. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/feedback.md +149 -0
  6. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/form-controls.md +313 -0
  7. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/layout-manager.md +420 -0
  8. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/layout.md +225 -0
  9. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-components/references/setup.md +166 -0
  10. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/SKILL.md +110 -0
  11. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/data-operations.md +445 -0
  12. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/editing.md +491 -0
  13. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/features.md +234 -0
  14. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/paging-remote.md +397 -0
  15. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/state.md +314 -0
  16. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/structure.md +299 -0
  17. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-grids/references/types.md +507 -0
  18. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-theming/SKILL.md +439 -0
  19. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-theming/references/common-patterns.md +45 -0
  20. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-theming/references/contributing.md +471 -0
  21. package/igx-ts/projects/_base/files/__dot__claude/skills/igniteui-angular-theming/references/mcp-setup.md +77 -0
  22. package/igx-ts/projects/_base/files/__dot__vscode/mcp.json +2 -2
  23. package/package.json +2 -2
@@ -0,0 +1,234 @@
1
+ # Grid Features — Grouping, Summaries, Toolbar, Export, Row Drag & More
2
+
3
+ > **Part of the [`igniteui-angular-grids`](../SKILL.md) skill hub.**
4
+ > For grid setup, column config, sorting, filtering, selection — see [`structure.md`](./structure.md).
5
+ > For Tree Grid, Hierarchical Grid, Grid Lite, Pivot Grid specifics — see [`types.md`](./types.md).
6
+ > For full editing coverage (cell/row/batch) — see [`editing.md`](./editing.md).
7
+
8
+ ## Contents
9
+
10
+ - [Editing](#editing)
11
+ - [Grouping (Grid only)](#grouping-grid-only)
12
+ - [Summaries](#summaries)
13
+ - [Cell Merging](#cell-merging)
14
+ - [Toolbar](#toolbar)
15
+ - [Export](#export)
16
+ - [Virtualization & Performance](#virtualization--performance)
17
+ - [Row Drag](#row-drag)
18
+ - [Action Strip](#action-strip)
19
+ - [Master-Detail (Grid only)](#master-detail-grid-only)
20
+ - [Clipboard](#clipboard)
21
+ - [Key Rules](#key-rules)
22
+
23
+ ## Editing
24
+
25
+ > **Full editing coverage is in [`editing.md`](./editing.md)**, which includes cell editing, row editing, batch editing with transactions, row adding/deleting, validation, and summaries. Use that reference for any editing task.
26
+
27
+ Quick reference:
28
+
29
+ | Mode | Key properties |
30
+ |---|---|
31
+ | **Cell editing** | `[editable]="true"` on columns + `(cellEditDone)` |
32
+ | **Row editing** (recommended default) | `[rowEditable]="true"` + `[editable]="true"` on columns + `(rowEditDone)` |
33
+ | **Batch editing** | `[batchEditing]="true"` + `[rowEditable]="true"` + `transactions.commit(data)` |
34
+
35
+ ## Grouping (Grid only)
36
+
37
+ > **Docs:** [Group By](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/groupby)
38
+
39
+ ```html
40
+ <igx-grid [data]="data()" [groupsExpanded]="true">
41
+ <igx-column field="category" [groupable]="true"></igx-column>
42
+
43
+ <!-- Custom group row template -->
44
+ <ng-template igxGroupByRow let-groupRow>
45
+ {{ groupRow.expression.fieldName }}: {{ groupRow.value }} ({{ groupRow.records.length }} items)
46
+ </ng-template>
47
+ </igx-grid>
48
+ ```
49
+
50
+ Programmatic:
51
+
52
+ ```typescript
53
+ this.gridRef().groupBy({ fieldName: 'category', dir: SortingDirection.Asc });
54
+ this.gridRef().clearGrouping('category');
55
+ ```
56
+
57
+ For advanced programmatic grouping patterns — see [`data-operations.md`](./data-operations.md).
58
+
59
+ ## Summaries
60
+
61
+ > **Full summaries coverage — built-in summaries, custom summary operands, and summaries with grouping — is in [`editing.md`](./editing.md#summaries).**
62
+ >
63
+ > Quick reference: enable per-column summaries with `[hasSummary]="true"` on an `igx-column`. Default operands: **number** → Count/Min/Max/Sum/Average; **date** → Count/Earliest/Latest; **string/boolean** → Count.
64
+
65
+ ## Cell Merging
66
+
67
+ Merge adjacent cells with equal values:
68
+
69
+ ```html
70
+ <igx-column field="category" [merge]="true"></igx-column>
71
+ ```
72
+
73
+ Or apply a custom merge strategy:
74
+
75
+ ```html
76
+ <igx-column field="price" [merge]="true" [mergeStrategy]="priceRangeMerge"></igx-column>
77
+ ```
78
+
79
+ ```typescript
80
+ import { IGridMergeStrategy } from 'igniteui-angular/core';
81
+ // import { IGridMergeStrategy } from '@infragistics/igniteui-angular/core'; for licensed package
82
+
83
+ priceRangeMerge: IGridMergeStrategy = {
84
+ shouldMerge(prevCell, curCell) {
85
+ return Math.abs(prevCell.value - curCell.value) < 10;
86
+ }
87
+ };
88
+ ```
89
+
90
+ ## Toolbar
91
+
92
+ > **Docs:** [Toolbar](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/toolbar)
93
+
94
+ ```typescript
95
+ import { IgxGridToolbarComponent } from 'igniteui-angular/grids/core';
96
+ ```
97
+
98
+ ```html
99
+ <igx-grid [data]="data()">
100
+ <igx-grid-toolbar>
101
+ <igx-grid-toolbar-title>Products</igx-grid-toolbar-title>
102
+ <igx-grid-toolbar-actions>
103
+ <igx-grid-toolbar-hiding></igx-grid-toolbar-hiding>
104
+ <igx-grid-toolbar-pinning></igx-grid-toolbar-pinning>
105
+ <igx-grid-toolbar-exporter></igx-grid-toolbar-exporter>
106
+ <igx-grid-toolbar-advanced-filtering></igx-grid-toolbar-advanced-filtering>
107
+ </igx-grid-toolbar-actions>
108
+ </igx-grid-toolbar>
109
+
110
+ <igx-column field="name"></igx-column>
111
+ </igx-grid>
112
+ ```
113
+
114
+ ## Export
115
+
116
+ ### Excel Export
117
+
118
+ > **Docs:** [Excel Export](https://www.infragistics.com/products/ignite-ui-angular/angular/components/exporter-excel)
119
+
120
+ ```typescript
121
+ import { IgxExcelExporterService, IgxExcelExporterOptions } from 'igniteui-angular/grids/core';
122
+
123
+ export class MyComponent {
124
+ private excelExporter = inject(IgxExcelExporterService);
125
+
126
+ exportToExcel() {
127
+ this.excelExporter.exportData(this.data(), new IgxExcelExporterOptions('export'));
128
+ // Or export the grid (respects filtering/sorting)
129
+ this.excelExporter.export(this.grid, new IgxExcelExporterOptions('export'));
130
+ }
131
+ }
132
+ ```
133
+
134
+ ### CSV Export
135
+
136
+ > **Docs:** [CSV Export](https://www.infragistics.com/products/ignite-ui-angular/angular/components/exporter-csv)
137
+
138
+ ```typescript
139
+ import { IgxCsvExporterService, IgxCsvExporterOptions, CsvFileTypes } from 'igniteui-angular/grids/core';
140
+
141
+ export class MyComponent {
142
+ private csvExporter = inject(IgxCsvExporterService);
143
+
144
+ exportToCsv() {
145
+ this.csvExporter.export(this.grid, new IgxCsvExporterOptions('export', CsvFileTypes.CSV));
146
+ }
147
+ }
148
+ ```
149
+
150
+ ## Virtualization & Performance
151
+
152
+ Grids use virtualization by default for both rows and columns — no setup needed. For remote data/paging:
153
+
154
+ ```html
155
+ <igx-grid [data]="data()" [totalItemCount]="totalCount" (dataPreLoad)="onDataPreLoad($event)">
156
+ </igx-grid>
157
+ ```
158
+
159
+ For full remote virtualization patterns — see [`paging-remote.md`](./paging-remote.md).
160
+
161
+ ## Row Drag
162
+
163
+ > **Docs:** [Row Drag](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/row-drag)
164
+
165
+ ```html
166
+ <igx-grid [rowDraggable]="true" (rowDragStart)="onDragStart($event)" (rowDragEnd)="onDragEnd($event)">
167
+ <ng-template igxRowDragGhost let-dragData>
168
+ <span>Moving {{ dragData.dragData.name }}</span>
169
+ </ng-template>
170
+ </igx-grid>
171
+ ```
172
+
173
+ ## Action Strip
174
+
175
+ > **Docs:** [Action Strip](https://www.infragistics.com/products/ignite-ui-angular/angular/components/action-strip)
176
+
177
+ Overlay actions on a row:
178
+
179
+ ```html
180
+ <igx-grid [data]="data()">
181
+ <igx-action-strip>
182
+ <igx-grid-editing-actions [addRow]="true"></igx-grid-editing-actions>
183
+ <igx-grid-pinning-actions></igx-grid-pinning-actions>
184
+ </igx-action-strip>
185
+ <igx-column field="name"></igx-column>
186
+ </igx-grid>
187
+ ```
188
+
189
+ ## Master-Detail (Grid only)
190
+
191
+ > **Docs:** [Master-Detail](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/master-detail)
192
+
193
+ Expand rows to show arbitrary detail content:
194
+
195
+ ```html
196
+ <igx-grid [data]="orders()" [primaryKey]="'orderId'">
197
+ <igx-column field="orderId"></igx-column>
198
+ <igx-column field="customer"></igx-column>
199
+
200
+ <ng-template igxGridDetail let-dataItem>
201
+ <div class="detail-container">
202
+ <h4>Order Items for {{ dataItem.customer }}</h4>
203
+ <igx-grid [data]="dataItem.items" [autoGenerate]="true" height="200px">
204
+ </igx-grid>
205
+ </div>
206
+ </ng-template>
207
+ </igx-grid>
208
+ ```
209
+
210
+ ## Clipboard
211
+
212
+ Grids support copy to clipboard by default. Configure via:
213
+
214
+ ```html
215
+ <igx-grid [clipboardOptions]="{ enabled: true, copyHeaders: true, copyFormatters: true, separator: '\t' }">
216
+ </igx-grid>
217
+ ```
218
+
219
+ ## Key Rules
220
+
221
+ 1. **Cancelable events** — use `event.cancel = true` in `(rowEdit)`, `(cellEdit)`, `(sorting)`, `(filtering)` to prevent the action
222
+ 2. **Use signals** for data binding — `[data]="myData()"` with `signal<T[]>([])`
223
+ 3. **Virtualization is automatic** — don't wrap grids in virtual scroll containers
224
+ 4. **GroupBy is Flat Grid only** — Tree Grid uses hierarchy, Hierarchical Grid uses row islands, Pivot Grid uses dimensions
225
+
226
+ ## See Also
227
+
228
+ - [`structure.md`](./structure.md) — Column config, sorting UI, filtering UI, selection
229
+ - [`types.md`](./types.md) — Tree Grid, Hierarchical Grid, Grid Lite, Pivot Grid specifics
230
+ - [`data-operations.md`](./data-operations.md) — Programmatic sorting, filtering, grouping
231
+ - [`paging-remote.md`](./paging-remote.md) — Paging, remote data operations, virtualization
232
+ - [`editing.md`](./editing.md) — Cell editing, row editing, batch editing, validation, summaries
233
+ - [`state.md`](./state.md) — State persistence
234
+ - [`../../igniteui-angular-theming/SKILL.md`](../../igniteui-angular-theming/SKILL.md) — Grid styling and theming
@@ -0,0 +1,397 @@
1
+ # Grid Paging, Remote Data & Virtualization
2
+
3
+ > **Part of the [`igniteui-angular-grids`](../SKILL.md) skill hub.**
4
+ > For grid import patterns and `viewChild` access — see [`data-operations.md`](./data-operations.md).
5
+ > For editing and validation — see [`editing.md`](./editing.md).
6
+ > For state persistence — see [`state.md`](./state.md).
7
+
8
+ ## Contents
9
+
10
+ - [Paging](#paging)
11
+ - [Remote Data Operations](#remote-data-operations)
12
+ - [Virtualization](#virtualization)
13
+ - [Multi-Grid Coordination](#multi-grid-coordination)
14
+ - [Key Rules](#key-rules)
15
+
16
+ ## Paging
17
+
18
+ > **Docs:** [Paging — Remote Paging](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/paging#remote-paging) (substitute URL prefix per grid type)
19
+
20
+ ### Using the Paginator Component
21
+
22
+ ```html
23
+ <igx-grid #grid
24
+ [data]="data()"
25
+ [primaryKey]="'id'"
26
+ height="600px">
27
+ <igx-column field="name"></igx-column>
28
+ <igx-column field="amount" dataType="number"></igx-column>
29
+
30
+ <igx-paginator
31
+ [perPage]="15"
32
+ [selectOptions]="[10, 15, 25, 50]"
33
+ [displayDensity]="'comfortable'">
34
+ </igx-paginator>
35
+ </igx-grid>
36
+ ```
37
+
38
+ ### Programmatic Paging
39
+
40
+ ```typescript
41
+ // Navigate pages
42
+ this.gridRef().paginator.page = 3;
43
+ this.gridRef().paginator.nextPage();
44
+ this.gridRef().paginator.previousPage();
45
+ this.gridRef().paginator.paginate(0); // go to first page
46
+
47
+ // Change page size
48
+ this.gridRef().paginator.perPage = 25;
49
+ ```
50
+
51
+ ### Paging Events
52
+
53
+ | Event | Description |
54
+ |---|---|
55
+ | `(paging)` | Fires before page changes (cancelable) |
56
+ | `(pagingDone)` | Fires after page has changed |
57
+ | `(perPageChange)` | Fires when page size changes |
58
+
59
+ ### Remote Paging
60
+
61
+ ```typescript
62
+ import { GridPagingMode } from 'igniteui-angular/grids/core';
63
+ import { IPageEventArgs } from 'igniteui-angular/paginator';
64
+
65
+ export class RemotePagingComponent {
66
+ data = signal<Product[]>([]);
67
+ totalCount = signal(0);
68
+ perPage = signal(15);
69
+ pagingMode = GridPagingMode.Remote;
70
+
71
+ gridRef = viewChild.required<IgxGridComponent>('grid');
72
+ private dataService = inject(ProductService);
73
+
74
+ constructor() {
75
+ this.loadPage(0);
76
+ }
77
+
78
+ onPagingDone(event: IPageEventArgs) {
79
+ this.loadPage(event.current);
80
+ }
81
+
82
+ onPerPageChange(perPage: number) {
83
+ this.perPage.set(perPage);
84
+ this.loadPage(0);
85
+ }
86
+
87
+ private loadPage(pageIndex: number) {
88
+ const skip = pageIndex * this.perPage();
89
+ this.dataService.getProducts({ skip, take: this.perPage() }).subscribe(result => {
90
+ this.data.set(result.data);
91
+ this.totalCount.set(result.totalCount);
92
+ });
93
+ }
94
+ }
95
+ ```
96
+
97
+ ```html
98
+ <igx-grid #grid
99
+ [data]="data()"
100
+ [primaryKey]="'id'"
101
+ [pagingMode]="pagingMode"
102
+ height="600px">
103
+ <igx-column field="name"></igx-column>
104
+ <igx-column field="price" dataType="number"></igx-column>
105
+
106
+ <igx-paginator
107
+ [perPage]="perPage()"
108
+ [totalRecords]="totalCount()"
109
+ (pagingDone)="onPagingDone($event)"
110
+ (perPageChange)="onPerPageChange($event)">
111
+ </igx-paginator>
112
+ </igx-grid>
113
+ ```
114
+
115
+ ## Remote Data Operations
116
+
117
+ > **Docs:** [Remote Data Operations](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/remote-data-operations) (substitute URL prefix per grid type)
118
+
119
+ ### The Problem
120
+
121
+ Grids perform sorting, filtering, and paging **client-side** by default. For large datasets, you must intercept these operations and delegate them to the server.
122
+
123
+ ### Complete Remote Data Pattern
124
+
125
+ This is the canonical pattern for server-side sorting, filtering, and virtualization. **You must disable the built-in client-side sorting/filtering** by applying `NoopSortingStrategy` and `NoopFilteringStrategy` on the grid:
126
+
127
+ ```typescript
128
+ import { Component, ChangeDetectionStrategy, signal, viewChild, inject, DestroyRef } from '@angular/core';
129
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
130
+ import { IgxGridComponent, IGX_GRID_DIRECTIVES } from 'igniteui-angular/grids/grid';
131
+ import {
132
+ IFilteringExpressionsTree,
133
+ NoopSortingStrategy,
134
+ NoopFilteringStrategy
135
+ } from 'igniteui-angular/core';
136
+ import { IForOfState } from 'igniteui-angular/directives';
137
+ import { ISortingEventArgs } from 'igniteui-angular/grids/core';
138
+ import { debounceTime, Subject } from 'rxjs';
139
+
140
+ @Component({
141
+ selector: 'app-remote-grid',
142
+ imports: [IGX_GRID_DIRECTIVES],
143
+ templateUrl: './remote-grid.component.html',
144
+ changeDetection: ChangeDetectionStrategy.OnPush
145
+ })
146
+ export class RemoteGridComponent {
147
+ data = signal<Order[]>([]);
148
+ totalCount = signal(0);
149
+ isLoading = signal(false);
150
+
151
+ // Noop strategies — disable built-in client-side sort/filter
152
+ noopSort = NoopSortingStrategy.instance();
153
+ noopFilter = NoopFilteringStrategy.instance();
154
+
155
+ gridRef = viewChild.required<IgxGridComponent>('grid');
156
+ private dataService = inject(OrderService);
157
+ private destroyRef = inject(DestroyRef);
158
+
159
+ private currentSort: ISortingEventArgs[] | undefined;
160
+ private currentFilter: IFilteringExpressionsTree | undefined;
161
+
162
+ // Debounce rapid dataPreLoad events during fast scrolling
163
+ private dataPreLoad$ = new Subject<IForOfState>();
164
+
165
+ constructor() {
166
+ this.dataPreLoad$.pipe(
167
+ debounceTime(150),
168
+ takeUntilDestroyed(this.destroyRef)
169
+ ).subscribe(event => {
170
+ // NOTE: The first chunkSize will always be 0 — use a reasonable default
171
+ const chunkSize = event.chunkSize || 15;
172
+ this.loadData(event.startIndex, chunkSize);
173
+ });
174
+
175
+ this.loadData(0, 15);
176
+ }
177
+
178
+ onDataPreLoad(event: IForOfState) {
179
+ this.dataPreLoad$.next(event);
180
+ }
181
+
182
+ onSortingDone(event: ISortingEventArgs) {
183
+ this.currentSort = this.gridRef().sortingExpressions;
184
+ this.loadData(0, 15);
185
+ }
186
+
187
+ onFilteringExpressionsTreeChange() {
188
+ this.currentFilter = this.gridRef().filteringExpressionsTree;
189
+ this.loadData(0, 15);
190
+ }
191
+
192
+ private loadData(skip: number, take: number) {
193
+ this.isLoading.set(true);
194
+ this.dataService.getOrders({
195
+ skip,
196
+ take,
197
+ sort: this.currentSort,
198
+ filter: this.currentFilter
199
+ }).subscribe(result => {
200
+ this.data.set(result.data);
201
+ this.totalCount.set(result.total);
202
+ this.isLoading.set(false);
203
+ });
204
+ }
205
+ }
206
+ ```
207
+
208
+ ```html
209
+ <igx-grid #grid
210
+ [data]="data()"
211
+ [primaryKey]="'orderId'"
212
+ [totalItemCount]="totalCount()"
213
+ [isLoading]="isLoading()"
214
+ [autoGenerate]="false"
215
+ [allowFiltering]="true"
216
+ [filterMode]="'excelStyleFilter'"
217
+ [sortStrategy]="noopSort"
218
+ [filterStrategy]="noopFilter"
219
+ (dataPreLoad)="onDataPreLoad($event)"
220
+ (sortingDone)="onSortingDone($event)"
221
+ (filteringExpressionsTreeChange)="onFilteringExpressionsTreeChange()"
222
+ height="600px">
223
+
224
+ <igx-column field="orderId" header="Order ID" [sortable]="true"></igx-column>
225
+ <igx-column field="customer" header="Customer" [sortable]="true" [filterable]="true"></igx-column>
226
+ <igx-column field="orderDate" header="Date" dataType="date" [sortable]="true" [filterable]="true"></igx-column>
227
+ <igx-column field="amount" header="Amount" dataType="number" [sortable]="true" [filterable]="true"></igx-column>
228
+ <igx-column field="status" header="Status" [filterable]="true"></igx-column>
229
+ </igx-grid>
230
+ ```
231
+
232
+ > **IMPORTANT**: `[sortStrategy]="noopSort"` and `[filterStrategy]="noopFilter"` prevent the grid from applying sort/filter operations client-side. The grid still fires events (allowing you to send them to the server), but the local data remains untouched until you replace it.
233
+
234
+ ### Excel-Style Filtering with Remote Unique Values
235
+
236
+ When using Excel-style filtering with remote data, provide a strategy to fetch unique column values from the server:
237
+
238
+ ```typescript
239
+ // Tell the grid how to load unique values for Excel-style filter lists
240
+ uniqueValuesStrategy = (column: any, tree: any, done: (values: any[]) => void) => {
241
+ this.dataService.getUniqueValues(column.field).subscribe(values => done(values));
242
+ };
243
+ ```
244
+
245
+ ```html
246
+ <igx-grid #grid
247
+ [data]="data()"
248
+ [uniqueColumnValuesStrategy]="uniqueValuesStrategy"
249
+ [filterMode]="'excelStyleFilter'"
250
+ [allowFiltering]="true">
251
+ </igx-grid>
252
+ ```
253
+
254
+ ### Remote Data Service Example
255
+
256
+ ```typescript
257
+ import { Injectable, inject } from '@angular/core';
258
+ import { HttpClient, HttpParams } from '@angular/common/http';
259
+ import { Observable } from 'rxjs';
260
+
261
+ export interface RemoteDataResult<T> {
262
+ data: T[];
263
+ total: number;
264
+ }
265
+
266
+ @Injectable({ providedIn: 'root' })
267
+ export class OrderService {
268
+ private http = inject(HttpClient);
269
+ private apiUrl = '/api/orders';
270
+
271
+ getOrders(params: {
272
+ skip: number;
273
+ take: number;
274
+ sort?: any[];
275
+ filter?: any;
276
+ }): Observable<RemoteDataResult<Order>> {
277
+ let httpParams = new HttpParams()
278
+ .set('skip', params.skip)
279
+ .set('take', params.take);
280
+
281
+ if (params.sort?.length) {
282
+ httpParams = httpParams.set('sort', JSON.stringify(params.sort));
283
+ }
284
+ if (params.filter) {
285
+ httpParams = httpParams.set('filter', JSON.stringify(params.filter));
286
+ }
287
+
288
+ return this.http.get<RemoteDataResult<Order>>(this.apiUrl, { params: httpParams });
289
+ }
290
+ }
291
+ ```
292
+
293
+ ### Key Points for Remote Data
294
+
295
+ 1. **Set `[totalItemCount]`** — the grid needs the total record count for correct virtual scrollbar sizing
296
+ 2. **Use `[isLoading]`** — shows a loading indicator while data is being fetched
297
+ 3. **Apply `NoopSortingStrategy` and `NoopFilteringStrategy`** — prevents the grid from performing client-side sorting/filtering, so the server results are displayed as-is
298
+ 4. **Listen to `(dataPreLoad)`** — fires when the user scrolls and the grid needs more rows; provides `startIndex` and `chunkSize` (first `chunkSize` will be 0 — use a fallback)
299
+ 5. **Listen to `(sortingDone)` and `(filteringExpressionsTreeChange)`** — reset to the beginning and re-fetch with new parameters; `filteringExpressionsTreeChange` is the grid-level output that reflects the complete filter state (unlike the column-level `filteringDone`)
300
+ 6. **Track current sort/filter state** — store them so every `loadData` call includes the active criteria
301
+ 7. **Debounce `(dataPreLoad)`** — use `debounceTime` to avoid flooding the server during fast scrolling
302
+ 8. **Use `[uniqueColumnValuesStrategy]`** — when using Excel-style filtering, supply a callback to load unique column values from the server
303
+
304
+ ## Virtualization
305
+
306
+ ### How It Works
307
+
308
+ All Ignite UI grids use **row and column virtualization** by default. Only the visible rows and columns are rendered in the DOM, enabling smooth scrolling through millions of records.
309
+
310
+ ### Requirements
311
+
312
+ - Set a fixed `height` on the grid (e.g., `height="600px"`)
313
+ - No additional configuration is needed — virtualization is automatic
314
+ - Do **not** wrap the grid in a virtual scroll container
315
+
316
+ ### Remote Virtualization
317
+
318
+ For datasets too large to load entirely, combine virtualization with remote data:
319
+
320
+ ```html
321
+ <igx-grid #grid
322
+ [data]="data()"
323
+ [totalItemCount]="totalCount()"
324
+ (dataPreLoad)="onDataPreLoad($event)"
325
+ height="600px">
326
+ </igx-grid>
327
+ ```
328
+
329
+ The `(dataPreLoad)` event fires with an `IForOfState` containing:
330
+ - `startIndex` — the first visible row index
331
+ - `chunkSize` — number of rows the grid needs
332
+
333
+ ## Multi-Grid Coordination
334
+
335
+ ### Master-Detail Filtering
336
+
337
+ When using a master grid to drive a detail grid:
338
+
339
+ ```typescript
340
+ export class MasterDetailComponent {
341
+ masterGrid = viewChild.required<IgxGridComponent>('masterGrid');
342
+ orders = signal<Order[]>([]);
343
+ selectedCustomer = signal<Customer | null>(null);
344
+ customerOrders = signal<Order[]>([]);
345
+
346
+ onRowSelectionChanging(event: IRowSelectionEventArgs) {
347
+ const selectedId = event.newSelection[0];
348
+ const customer = this.customers().find(c => c.id === selectedId);
349
+ this.selectedCustomer.set(customer ?? null);
350
+
351
+ if (customer) {
352
+ this.dataService.getOrdersByCustomer(customer.id).subscribe(orders => {
353
+ this.customerOrders.set(orders);
354
+ });
355
+ }
356
+ }
357
+ }
358
+ ```
359
+
360
+ ```html
361
+ <igx-grid #masterGrid
362
+ [data]="customers()"
363
+ [primaryKey]="'id'"
364
+ [rowSelection]="'single'"
365
+ (rowSelectionChanging)="onRowSelectionChanging($event)"
366
+ height="300px">
367
+ <igx-column field="name" header="Customer"></igx-column>
368
+ </igx-grid>
369
+
370
+ <igx-grid
371
+ [data]="customerOrders()"
372
+ [primaryKey]="'orderId'"
373
+ height="300px">
374
+ <igx-column field="orderId" header="Order"></igx-column>
375
+ <igx-column field="amount" header="Amount" dataType="number"></igx-column>
376
+ </igx-grid>
377
+ ```
378
+
379
+ ## Key Rules
380
+
381
+ 1. **Remote data requires `[totalItemCount]`** — without it, the virtual scrollbar won't size correctly
382
+ 2. **Remote data requires noop strategies** — apply `NoopSortingStrategy` and `NoopFilteringStrategy` to disable client-side operations when the server handles them
383
+ 3. **Track sort/filter state for remote operations** — store current expressions and include them in every server request
384
+ 4. **Debounce rapid virtual scroll** — use `debounceTime` on `(dataPreLoad)` to avoid flooding the server
385
+ 5. **Virtualization is automatic** — don't wrap grids in virtual scroll containers; just set a fixed `height`
386
+ 6. **Use the correct component type for `viewChild`** — `IgxGridComponent`, `IgxTreeGridComponent`, `IgxHierarchicalGridComponent`, or `IgxPivotGridComponent`
387
+ 7. **Import the correct directives/components** — `IGX_GRID_DIRECTIVES`, `IGX_TREE_GRID_DIRECTIVES`, `IGX_HIERARCHICAL_GRID_DIRECTIVES`, or `IGX_PIVOT_GRID_DIRECTIVES`
388
+ 8. **Use signals for data** — `[data]="myData()"` with `signal<T[]>([])`
389
+
390
+ ## See Also
391
+
392
+ - [`data-operations.md`](./data-operations.md) — Sorting, filtering, grouping, and canonical grid import patterns
393
+ - [`editing.md`](./editing.md) — Cell editing, row editing, batch editing, validation, summaries
394
+ - [`state.md`](./state.md) — State persistence, Tree Grid / Hierarchical Grid / Pivot Grid / Grid Lite data operations
395
+ - [`structure.md`](./structure.md) — Grid structure, column configuration, templates, layout, selection
396
+ - [`../../igniteui-angular-components/SKILL.md`](../../igniteui-angular-components/SKILL.md) — Non-grid Ignite UI components
397
+ - [`../../igniteui-angular-theming/SKILL.md`](../../igniteui-angular-theming/SKILL.md) — Theming & Styling