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

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,491 @@
1
+ # Grid Editing — Cell Editing, Row Editing, Batch Editing & Validation
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 state persistence — see [`state.md`](./state.md).
6
+ > For paging and remote data — see [`paging-remote.md`](./paging-remote.md).
7
+
8
+ ## Contents
9
+
10
+ - [Editing Data Through the Grid](#editing-data-through-the-grid)
11
+ - [Batch Editing & Transactions](#batch-editing--transactions)
12
+ - [Excel-Style Editing Workflows](#excel-style-editing-workflows)
13
+ - [Editing Events Reference](#editing-events-reference)
14
+ - [Validation](#validation)
15
+ - [Summaries](#summaries)
16
+ - [Key Rules](#key-rules)
17
+
18
+ ## Editing Data Through the Grid
19
+
20
+ > **AGENT INSTRUCTION:** When a user says they want to "edit data through the grid", "make the grid editable", or "allow CRUD in the grid", use this section to pick the right editing mode before writing any code.
21
+
22
+ ### Choosing an Editing Mode
23
+
24
+ | Mode | When to use | Key properties |
25
+ |---|---|---|
26
+ | **Cell editing** | Each cell saves immediately when the user confirms or leaves it. Good for quick single-field corrections. | `[editable]="true"` on columns + `(cellEditDone)` |
27
+ | **Row editing** | User edits multiple cells in a row and confirms/cancels the whole row at once. **Best for most CRUD UIs.** | `[rowEditable]="true"` + `[editable]="true"` on columns + `(rowEditDone)` |
28
+ | **Batch editing** | Accumulate many changes across multiple rows with undo/redo, then commit or discard all at once. | `[batchEditing]="true"` + `[rowEditable]="true"` |
29
+
30
+ > **Default recommendation:** use **row editing** for most data management UIs (e.g., "edit available cars"). It prevents half-edited data from being visible and gives users a clear Done/Cancel flow per row.
31
+
32
+ ### Cell Editing (Immediate)
33
+
34
+ > **Docs:** [Cell Editing](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/cell-editing)
35
+
36
+ The simplest mode. Each cell saves the moment the user tabs away or presses Enter.
37
+
38
+ ```typescript
39
+ import { Component, ChangeDetectionStrategy, signal, viewChild, inject } from '@angular/core';
40
+ import { IgxGridComponent, IGX_GRID_DIRECTIVES } from 'igniteui-angular/grids/grid';
41
+ import { IGridEditDoneEventArgs } from 'igniteui-angular/grids/core';
42
+
43
+ @Component({
44
+ selector: 'app-cars-grid',
45
+ imports: [IGX_GRID_DIRECTIVES],
46
+ templateUrl: './cars-grid.component.html',
47
+ changeDetection: ChangeDetectionStrategy.OnPush
48
+ })
49
+ export class CarsGridComponent {
50
+ gridRef = viewChild.required<IgxGridComponent>('grid');
51
+ private carService = inject(CarService);
52
+ protected cars = signal<Car[]>([]);
53
+
54
+ constructor() {
55
+ this.carService.getCars().subscribe(data => this.cars.set(data));
56
+ }
57
+
58
+ onCellEditDone(event: IGridEditDoneEventArgs) {
59
+ // Persist the single-cell change immediately
60
+ const updatedCar = { ...event.rowData, [event.column.field]: event.newValue };
61
+ this.carService.updateCar(updatedCar).subscribe();
62
+ }
63
+ }
64
+ ```
65
+
66
+ ```html
67
+ <igx-grid #grid
68
+ [data]="cars()"
69
+ [primaryKey]="'id'"
70
+ [autoGenerate]="false"
71
+ (cellEditDone)="onCellEditDone($event)"
72
+ height="600px">
73
+ <igx-column field="make" header="Make" [editable]="true" [sortable]="true"></igx-column>
74
+ <igx-column field="model" header="Model" [editable]="true" [sortable]="true"></igx-column>
75
+ <igx-column field="year" header="Year" dataType="number" [editable]="true" [sortable]="true"></igx-column>
76
+ <igx-column field="price" header="Price" dataType="number" [editable]="true" [sortable]="true"></igx-column>
77
+ <igx-column field="available" header="Available" dataType="boolean" [editable]="true"></igx-column>
78
+ </igx-grid>
79
+ ```
80
+
81
+ ### Row Editing (Recommended for CRUD)
82
+
83
+ > **Docs:** [Row Editing](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/row-editing)
84
+
85
+ Users click into a row, edit cells, then click **Done** or **Cancel** — changes only apply when Done is pressed. An overlay toolbar appears automatically.
86
+
87
+ ```typescript
88
+ import { Component, ChangeDetectionStrategy, signal, viewChild, inject } from '@angular/core';
89
+ import { IgxGridComponent, IGX_GRID_DIRECTIVES } from 'igniteui-angular/grids/grid';
90
+ import { IGridEditDoneEventArgs, IGridEditEventArgs, IRowDataEventArgs } from 'igniteui-angular/grids/core';
91
+
92
+ @Component({
93
+ selector: 'app-cars-grid',
94
+ imports: [IGX_GRID_DIRECTIVES],
95
+ templateUrl: './cars-grid.component.html',
96
+ changeDetection: ChangeDetectionStrategy.OnPush
97
+ })
98
+ export class CarsGridComponent {
99
+ gridRef = viewChild.required<IgxGridComponent>('grid');
100
+ private carService = inject(CarService);
101
+ protected cars = signal<Car[]>([]);
102
+
103
+ constructor() {
104
+ this.carService.getCars().subscribe(data => this.cars.set(data));
105
+ }
106
+
107
+ onRowEditDone(event: IGridEditDoneEventArgs) {
108
+ // event.newValue contains the full updated row object
109
+ this.carService.updateCar(event.newValue).subscribe();
110
+ }
111
+
112
+ onRowAdded(event: IRowDataEventArgs) {
113
+ // Persist the newly added row; optionally replace local data with server response
114
+ this.carService.createCar(event.data).subscribe(created => {
115
+ this.cars.update(cars => cars.map(c => c === event.data ? created : c));
116
+ });
117
+ }
118
+
119
+ onRowDeleted(event: IRowDataEventArgs) {
120
+ this.carService.deleteCar(event.data.id).subscribe();
121
+ }
122
+
123
+ addCar() {
124
+ // Programmatically start a new row at the end
125
+ this.gridRef().beginAddRowByIndex(this.cars().length);
126
+ }
127
+
128
+ deleteCar(carId: number) {
129
+ this.gridRef().deleteRow(carId);
130
+ }
131
+ }
132
+ ```
133
+
134
+ ```html
135
+ <igx-grid #grid
136
+ [data]="cars()"
137
+ [primaryKey]="'id'"
138
+ [autoGenerate]="false"
139
+ [rowEditable]="true"
140
+ (rowEditDone)="onRowEditDone($event)"
141
+ (rowAdded)="onRowAdded($event)"
142
+ (rowDeleted)="onRowDeleted($event)"
143
+ height="600px">
144
+
145
+ <igx-column field="make" header="Make" [editable]="true" [sortable]="true"></igx-column>
146
+ <igx-column field="model" header="Model" [editable]="true" [sortable]="true"></igx-column>
147
+ <igx-column field="year" header="Year" dataType="number" [editable]="true" [sortable]="true"></igx-column>
148
+ <igx-column field="price" header="Price" dataType="number" [editable]="true" [sortable]="true"></igx-column>
149
+ <igx-column field="available" header="Available" dataType="boolean" [editable]="true"></igx-column>
150
+
151
+ <!-- Action strip: shows Edit and Delete buttons on row hover; Add Row button in toolbar -->
152
+ <igx-action-strip>
153
+ <igx-grid-editing-actions [addRow]="true"></igx-grid-editing-actions>
154
+ </igx-action-strip>
155
+ </igx-grid>
156
+
157
+ <button (click)="addCar()">Add Car</button>
158
+ ```
159
+
160
+ > **Key inputs summary:**
161
+ > - `[rowEditable]="true"` — enables the Done/Cancel overlay per row
162
+ > - `[editable]="true"` on each `igx-column` — marks which fields the user can change
163
+ > - `[primaryKey]` — **required** for editing to work
164
+ > - `[autoGenerate]="false"` — always define columns explicitly when editing is enabled so you control which fields are editable
165
+ > - `<igx-action-strip>` with `<igx-grid-editing-actions>` — adds hover Edit/Delete buttons and an optional Add Row button automatically
166
+
167
+ ### Programmatic Row Adding with Default Values
168
+
169
+ When starting a new row programmatically, pre-populate fields using `(cellEditEnter)` on the new row:
170
+
171
+ ```typescript
172
+ onCellEditEnter(event: IGridEditEventArgs) {
173
+ if (event.isAddRow && event.column.field === 'available') {
174
+ event.cellEditArgs.newValue = true; // default new cars to available
175
+ }
176
+ if (event.isAddRow && event.column.field === 'year') {
177
+ event.cellEditArgs.newValue = new Date().getFullYear();
178
+ }
179
+ }
180
+ ```
181
+
182
+ ```html
183
+ <igx-grid #grid ... (cellEditEnter)="onCellEditEnter($event)">
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Batch Editing & Transactions
189
+
190
+ > **Docs:** [Batch Editing](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/batch-editing) (substitute URL prefix per grid type)
191
+
192
+ > **Applies to**: Flat Grid, Tree Grid, and Hierarchical Grid. **Pivot Grid does NOT support batch editing.**
193
+ > Use batch editing when users need to **edit many rows at once** and commit or discard all changes together, with undo/redo support.
194
+
195
+ ### Enabling Batch Editing
196
+
197
+ ```html
198
+ <igx-grid #grid
199
+ [data]="data()"
200
+ [primaryKey]="'id'"
201
+ [batchEditing]="true"
202
+ [rowEditable]="true"
203
+ height="600px">
204
+ <igx-column field="name" [editable]="true"></igx-column>
205
+ <igx-column field="price" dataType="number" [editable]="true"></igx-column>
206
+ <igx-column field="quantity" dataType="number" [editable]="true"></igx-column>
207
+ </igx-grid>
208
+
209
+ <button (click)="commitChanges()">Save All</button>
210
+ <button (click)="undoLast()">Undo</button>
211
+ <button (click)="redoLast()">Redo</button>
212
+ <button (click)="discardAll()">Discard</button>
213
+ ```
214
+
215
+ ### Managing Transactions
216
+
217
+ ```typescript
218
+ commitChanges() {
219
+ // Exit any active edit before committing
220
+ this.gridRef().endEdit(true);
221
+ this.gridRef().transactions.commit(this.gridRef().data);
222
+ }
223
+
224
+ undoLast() {
225
+ // Must exit edit mode before undo/redo
226
+ this.gridRef().endEdit(true);
227
+ this.gridRef().transactions.undo();
228
+ }
229
+
230
+ redoLast() {
231
+ this.gridRef().endEdit(true);
232
+ this.gridRef().transactions.redo();
233
+ }
234
+
235
+ discardAll() {
236
+ this.gridRef().endEdit(false);
237
+ this.gridRef().transactions.clear();
238
+ }
239
+ ```
240
+
241
+ Use `canUndo` and `canRedo` to control button state:
242
+
243
+ ```html
244
+ <button (click)="commitChanges()" [disabled]="gridRef().transactions.getAggregatedChanges(false).length < 1">Save All</button>
245
+ <button (click)="undoLast()" [disabled]="!gridRef().transactions.canUndo">Undo</button>
246
+ <button (click)="redoLast()" [disabled]="!gridRef().transactions.canRedo">Redo</button>
247
+ <button (click)="discardAll()">Discard</button>
248
+ ```
249
+
250
+ ### Transaction State
251
+
252
+ ```typescript
253
+ // Check if there are pending changes
254
+ const hasPendingChanges = this.gridRef().transactions.getAggregatedChanges(false).length > 0;
255
+
256
+ // Get all pending transactions
257
+ const pending = this.gridRef().transactions.getAggregatedChanges(true);
258
+ // Each transaction has: { id, type ('add'|'update'|'delete'), newValue }
259
+ ```
260
+
261
+ ### Sending Batch Changes to Server
262
+
263
+ ```typescript
264
+ saveToServer() {
265
+ const changes = this.gridRef().transactions.getAggregatedChanges(true);
266
+
267
+ const adds = changes.filter(t => t.type === 'add').map(t => t.newValue);
268
+ const updates = changes.filter(t => t.type === 'update').map(t => ({ id: t.id, ...t.newValue }));
269
+ const deletes = changes.filter(t => t.type === 'delete').map(t => t.id);
270
+
271
+ this.dataService.saveBatch({ adds, updates, deletes }).subscribe(() => {
272
+ this.gridRef().transactions.commit(this.gridRef().data);
273
+ this.gridRef().transactions.clear();
274
+ });
275
+ }
276
+ ```
277
+
278
+ ## Excel-Style Editing Workflows
279
+
280
+ ### Inline Cell Editing with Validation
281
+
282
+ ```html
283
+ <igx-grid #grid
284
+ [data]="data()"
285
+ [primaryKey]="'id'"
286
+ [batchEditing]="true"
287
+ (cellEditDone)="onCellEditDone($event)">
288
+
289
+ <igx-column field="name" [editable]="true" required></igx-column>
290
+ <igx-column field="email" [editable]="true" [validators]="emailValidators"></igx-column>
291
+ <igx-column field="quantity" dataType="number" [editable]="true" [validators]="quantityValidators"></igx-column>
292
+ </igx-grid>
293
+ ```
294
+
295
+ ```typescript
296
+ import { Validators } from '@angular/forms';
297
+
298
+ emailValidators = [Validators.required, Validators.email];
299
+ quantityValidators = [Validators.required, Validators.min(0), Validators.max(9999)];
300
+
301
+ onCellEditDone(event: IGridEditDoneEventArgs) {
302
+ // React to edits — e.g., recalculate totals
303
+ if (event.column.field === 'quantity' || event.column.field === 'unitPrice') {
304
+ this.recalculateRowTotal(event.rowID);
305
+ }
306
+ }
307
+ ```
308
+
309
+ ### Clipboard Paste for Bulk Edit
310
+
311
+ Grids support paste from Excel/spreadsheets by default. Configure clipboard behavior:
312
+
313
+ ```html
314
+ <igx-grid #grid
315
+ [data]="data()"
316
+ [primaryKey]="'id'"
317
+ [batchEditing]="true"
318
+ [clipboardOptions]="{ enabled: true, copyHeaders: true, copyFormatters: true, separator: '\t' }">
319
+ </igx-grid>
320
+ ```
321
+
322
+ ### Row Adding via UI
323
+
324
+ ```typescript
325
+ // Flat Grid / Hierarchical Grid:
326
+ this.gridRef().beginAddRowByIndex(0); // at top
327
+ this.gridRef().beginAddRowById('ALFKI'); // under a specific row
328
+ this.gridRef().beginAddRowByIndex(this.gridRef().data.length); // at end
329
+
330
+ // Tree Grid — add as child of a parent:
331
+ this.treeGridRef().addRow(newRowData, parentRowID); // add row as child of parentRowID
332
+ this.treeGridRef().beginAddRowByIndex(3, true); // add as child of row at index 3
333
+ ```
334
+
335
+ Use with Action Strip for visual add/edit actions:
336
+
337
+ ```html
338
+ <igx-grid #grid [data]="data()" [primaryKey]="'id'" [rowEditable]="true">
339
+ <igx-action-strip>
340
+ <igx-grid-editing-actions [addRow]="true"></igx-grid-editing-actions>
341
+ </igx-action-strip>
342
+ <igx-column field="name" [editable]="true"></igx-column>
343
+ </igx-grid>
344
+ ```
345
+
346
+ ## Editing Events Reference
347
+
348
+ All grids fire a consistent sequence of events during cell and row editing:
349
+
350
+ | Event | Fires When | Cancelable |
351
+ |---|---|---|
352
+ | `(rowEditEnter)` | Row enters edit mode | Yes |
353
+ | `(cellEditEnter)` | Cell enters edit mode (after `rowEditEnter`) | Yes |
354
+ | `(cellEdit)` | Cell value is about to be committed | Yes |
355
+ | `(cellEditDone)` | Cell value has been committed | No |
356
+ | `(cellEditExit)` | Cell exits edit mode | No |
357
+ | `(rowEdit)` | Row edit is about to be committed (Done button) | Yes |
358
+ | `(rowEditDone)` | Row edit has been committed | No |
359
+ | `(rowEditExit)` | Row exits edit mode | No |
360
+
361
+ Canceling `(cellEdit)` keeps the cell in edit mode — the value won't commit until Cancel is clicked:
362
+
363
+ ```typescript
364
+ onCellEdit(event: IGridEditEventArgs) {
365
+ if (!event.valid) {
366
+ event.cancel = true; // prevent committing invalid values
367
+ }
368
+ }
369
+ ```
370
+
371
+ ## Validation
372
+
373
+ > **Docs:** [Validation](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/validation)
374
+
375
+ ### Template-Driven Validation
376
+
377
+ Apply Angular validators directly on columns:
378
+
379
+ ```html
380
+ <igx-column field="email" [editable]="true" required email></igx-column>
381
+ <igx-column field="age" dataType="number" [editable]="true" required [min]="18" [max]="120"></igx-column>
382
+ ```
383
+
384
+ Supported built-in validators: `required`, `min`, `max`, `email`, `minlength`, `maxlength`, `pattern`.
385
+
386
+ ### Reactive Form Validation
387
+
388
+ Use the `formGroupCreated` event to add custom validators when a row enters edit mode:
389
+
390
+ ```html
391
+ <igx-grid #grid [data]="data()" [rowEditable]="true" [primaryKey]="'id'"
392
+ (formGroupCreated)="onFormGroupCreated($event)">
393
+ </igx-grid>
394
+ ```
395
+
396
+ ```typescript
397
+ onFormGroupCreated(event: IGridFormGroupCreatedEventArgs) {
398
+ const { formGroup } = event;
399
+ formGroup.get('endDate')?.addValidators(this.dateAfterValidator('startDate'));
400
+ }
401
+ ```
402
+
403
+ ### Validation Service
404
+
405
+ The grid exposes a `validation` service:
406
+
407
+ ```typescript
408
+ // Check if the grid is in a valid state
409
+ const isValid = this.gridRef().validation.valid;
410
+
411
+ // Get all records with validation errors
412
+ const invalid = this.gridRef().validation.getInvalid();
413
+
414
+ // Clear validation state for a specific record (or all if no id)
415
+ this.gridRef().validation.clear(recordId);
416
+ ```
417
+
418
+ ## Summaries
419
+
420
+ > **Docs:** [Summaries](https://www.infragistics.com/products/ignite-ui-angular/angular/components/grid/summaries) (substitute URL prefix per grid type)
421
+
422
+ ### Built-In Summaries
423
+
424
+ ```html
425
+ <igx-column field="amount" dataType="number" [hasSummary]="true"></igx-column>
426
+ ```
427
+
428
+ Default summaries by type:
429
+ - **number**: Count, Min, Max, Sum, Average
430
+ - **date**: Count, Earliest, Latest
431
+ - **string/boolean**: Count
432
+
433
+ ### Custom Summary Operand
434
+
435
+ ```typescript
436
+ import { IgxNumberSummaryOperand } from 'igniteui-angular/grids/core';
437
+ import { IgxSummaryResult } from 'igniteui-angular/core';
438
+
439
+ class RevenueSummary extends IgxNumberSummaryOperand {
440
+ operate(data: number[]): IgxSummaryResult[] {
441
+ const result = super.operate(data);
442
+ result.push({
443
+ key: 'margin',
444
+ label: 'Avg Margin',
445
+ summaryResult: data.length ? data.reduce((a, b) => a + b, 0) / data.length * 0.15 : 0
446
+ });
447
+ return result;
448
+ }
449
+ }
450
+
451
+ // Use in component
452
+ revenueSummary = RevenueSummary;
453
+ ```
454
+
455
+ ```html
456
+ <igx-column field="revenue" dataType="number" [hasSummary]="true" [summaries]="revenueSummary"></igx-column>
457
+ ```
458
+
459
+ ### Summaries with Grouping
460
+
461
+ When grouping is enabled, summaries appear for each group. Control this with:
462
+
463
+ ```html
464
+ <igx-grid #grid
465
+ [data]="data()"
466
+ [showSummaryOnCollapse]="true"
467
+ [summaryCalculationMode]="'childLevelsOnly'"
468
+ [summaryPosition]="'bottom'">
469
+ </igx-grid>
470
+ ```
471
+
472
+ ## Key Rules
473
+
474
+ 1. **Choose the right editing mode** — cell editing (`[editable]` + `(cellEditDone)`) for immediate per-cell saves; row editing (`[rowEditable]="true"` + `(rowEditDone)`) for confirm/cancel per row (**recommended default for CRUD**); batch editing (`[batchEditing]="true"`) for accumulate-then-commit with undo/redo
475
+ 2. **`[primaryKey]` is required for all editing** — row editing, batch editing, row adding, and row deletion all depend on it (Flat, Tree, Hierarchical, Pivot grids; NOT Grid Lite)
476
+ 3. **Always set `[autoGenerate]="false"` when editing** — define columns explicitly and mark each with `[editable]="true"` to control exactly what users can change
477
+ 4. **Batch editing requires `[primaryKey]`** — call `endEdit(true)` before `transactions.undo()`/`redo()`, commit via `transactions.commit(data)`
478
+ 5. **Cancelable events** — use `event.cancel = true` in `(cellEdit)`, `(rowEdit)`, `(paging)` to prevent the action
479
+ 6. **Validation** — use template-driven validators on columns (`required`, `min`, `max`, `email`, `pattern`) or reactive validators via `(formGroupCreated)`
480
+ 7. **Use the correct component type for `viewChild`** — `IgxGridComponent`, `IgxTreeGridComponent`, `IgxHierarchicalGridComponent`, or `IgxPivotGridComponent`
481
+ 8. **Import the correct directives/components** — `IGX_GRID_DIRECTIVES`, `IGX_TREE_GRID_DIRECTIVES`, `IGX_HIERARCHICAL_GRID_DIRECTIVES`, or `IGX_PIVOT_GRID_DIRECTIVES`
482
+ 9. **Use signals for data** — `[data]="myData()"` with `signal<T[]>([])`
483
+
484
+ ## See Also
485
+
486
+ - [`data-operations.md`](./data-operations.md) — Sorting, filtering, grouping, and canonical grid import patterns
487
+ - [`paging-remote.md`](./paging-remote.md) — Paging, remote data operations, virtualization
488
+ - [`state.md`](./state.md) — State persistence, Tree Grid / Hierarchical Grid / Pivot Grid / Grid Lite data operations
489
+ - [`structure.md`](./structure.md) — Grid structure, column configuration, templates, layout, selection
490
+ - [`../../igniteui-angular-components/SKILL.md`](../../igniteui-angular-components/SKILL.md) — Non-grid Ignite UI components
491
+ - [`../../igniteui-angular-theming/SKILL.md`](../../igniteui-angular-theming/SKILL.md) — Theming & Styling