igniteui-cli 15.2.1-alpha.3 → 15.2.2-alpha.0

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 (15) hide show
  1. package/package.json +4 -4
  2. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-components/references/charts.md +39 -10
  3. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-components/references/data-display.md +6 -6
  4. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-components/references/feedback.md +5 -5
  5. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-components/references/form-controls.md +8 -8
  6. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-components/references/layout-manager.md +86 -15
  7. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-components/references/layout.md +13 -10
  8. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/data-operations.md +47 -20
  9. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/editing.md +34 -27
  10. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/features.md +70 -30
  11. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/paging-remote.md +23 -23
  12. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/sizing.md +22 -30
  13. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/state.md +47 -34
  14. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/structure.md +25 -22
  15. package/templates/blazor/igb/projects/ai-config/files/skills/igniteui-blazor-grids/references/types.md +27 -55
@@ -57,7 +57,7 @@ Mark columns as editable:
57
57
  | `CellEditEnter` | `EventCallback<IgbGridEditEventArgs>` | Fires when a cell enters edit mode |
58
58
  | `CellEdit` | `EventCallback<IgbGridEditEventArgs>` | Fires before a cell value is committed - set `args.Cancel = true` to reject |
59
59
  | `CellEditDone` | `EventCallback<IgbGridEditDoneEventArgs>` | Fires after a cell value is committed |
60
- | `CellEditExit` | `EventCallback<IgbGridEditEventArgs>` | Fires when a cell exits edit mode |
60
+ | `CellEditExit` | `EventCallback<IgbGridEditDoneEventArgs>` | Fires when a cell exits edit mode |
61
61
 
62
62
  ### Example: Validate before commit
63
63
 
@@ -126,7 +126,7 @@ Mark columns as editable:
126
126
  | `RowEditEnter` | `EventCallback<IgbGridEditEventArgs>` | Fires when a row enters edit mode |
127
127
  | `RowEdit` | `EventCallback<IgbGridEditEventArgs>` | Fires before row changes are committed - set `args.Cancel = true` to reject |
128
128
  | `RowEditDone` | `EventCallback<IgbGridEditDoneEventArgs>` | Fires after row changes are committed |
129
- | `RowEditExit` | `EventCallback<IgbGridEditEventArgs>` | Fires when a row exits edit mode |
129
+ | `RowEditExit` | `EventCallback<IgbGridEditDoneEventArgs>` | Fires when a row exits edit mode |
130
130
 
131
131
  ### Example: Save row on confirm
132
132
 
@@ -201,40 +201,32 @@ Add inline add/edit/delete actions:
201
201
 
202
202
  ## Validation
203
203
 
204
- ### Built-in validation
204
+ ### Custom validation via editing events
205
205
 
206
- Columns support built-in validators that run during editing:
207
-
208
- ```razor
209
- <IgbColumn Field="Name" Editable="true" Required="true" />
210
- <IgbColumn Field="Email" Editable="true" DataType="GridColumnDataType.String" MinLength="5" MaxLength="100" />
211
- <IgbColumn Field="Age" Editable="true" DataType="GridColumnDataType.Number" Min="18" Max="120" />
212
- ```
213
-
214
- | Validator Parameter | Type | Description |
215
- |---|---|---|
216
- | `Required` | `bool` | Value cannot be empty |
217
- | `MinLength` | `int` | Minimum string length |
218
- | `MaxLength` | `int` | Maximum string length |
219
- | `Min` | `object` | Minimum numeric/date value |
220
- | `Max` | `object` | Maximum numeric/date value |
221
-
222
- ### Validation display
223
-
224
- When a validation rule is violated, the cell shows a red border and a tooltip with the error message. The row cannot be committed while validation errors exist in row editing mode.
225
-
226
- ### Custom validation
227
-
228
- Implement custom logic in the `CellEdit` or `RowEdit` event:
206
+ Use the `CellEdit` or `RowEdit` event to validate values before commit. Set `args.Cancel = true` to reject invalid input:
229
207
 
230
208
  ```razor
231
209
  <IgbGrid Data="data" PrimaryKey="Id" RowEditable="true"
232
- RowEdit="OnRowEdit">
210
+ RowEdit="OnRowEdit" CellEdit="OnCellEdit">
211
+ <IgbColumn Field="Name" Editable="true" DataType="GridColumnDataType.String" />
212
+ <IgbColumn Field="Age" Editable="true" DataType="GridColumnDataType.Number" />
233
213
  <IgbColumn Field="StartDate" Editable="true" DataType="GridColumnDataType.Date" />
234
214
  <IgbColumn Field="EndDate" Editable="true" DataType="GridColumnDataType.Date" />
235
215
  </IgbGrid>
236
216
 
237
217
  @code {
218
+ private void OnCellEdit(IgbGridEditEventArgs args)
219
+ {
220
+ if (args.Column.Field == "Age")
221
+ {
222
+ var newValue = Convert.ToInt32(args.NewValue);
223
+ if (newValue < 18 || newValue > 120)
224
+ {
225
+ args.Cancel = true; // reject out-of-range age
226
+ }
227
+ }
228
+ }
229
+
238
230
  private void OnRowEdit(IgbGridEditEventArgs args)
239
231
  {
240
232
  var rowData = args.NewValue as ProjectTask;
@@ -247,6 +239,21 @@ Implement custom logic in the `CellEdit` or `RowEdit` event:
247
239
  }
248
240
  ```
249
241
 
242
+ ### Validation error template
243
+
244
+ Use `ErrorTemplate` on a column to display a custom message when validation fails:
245
+
246
+ ```razor
247
+ <IgbColumn Field="Age" Editable="true" DataType="GridColumnDataType.Number">
248
+ <ErrorTemplate>
249
+ @{
250
+ var cell = (IgbCellTemplateContext)context;
251
+ }
252
+ <span style="color: red;">Invalid value</span>
253
+ </ErrorTemplate>
254
+ </IgbColumn>
255
+ ```
256
+
250
257
  ---
251
258
 
252
259
  ## Custom Editors
@@ -68,15 +68,15 @@ Customize the group row:
68
68
  var groupRow = (IgbGroupByRowTemplateContext)context;
69
69
  }
70
70
  <span>
71
- <strong>@groupRow.GroupRow.Expression.FieldName</strong>:
72
- @groupRow.GroupRow.Value
73
- (@groupRow.GroupRow.Records.Count items)
71
+ <strong>@groupRow.Implicit.Expression.FieldName</strong>:
72
+ @groupRow.Implicit.Value
73
+ (@groupRow.Implicit.Records.Length items)
74
74
  </span>
75
75
  </GroupRowTemplate>
76
76
  </IgbGrid>
77
77
  ```
78
78
 
79
- ### Hide group area
79
+ ### Hide grouped columns from the grid
80
80
 
81
81
  ```razor
82
82
  <IgbGrid Data="data" PrimaryKey="Id" HideGroupedColumns="true">
@@ -84,6 +84,14 @@ Customize the group row:
84
84
  </IgbGrid>
85
85
  ```
86
86
 
87
+ ### Hide the group area
88
+
89
+ ```razor
90
+ <IgbGrid Data="data" PrimaryKey="Id" ShowGroupArea="false">
91
+ ...
92
+ </IgbGrid>
93
+ ```
94
+
87
95
  ### Grouping events
88
96
 
89
97
  | Event | Type | Description |
@@ -115,14 +123,9 @@ Enable with `HasSummary="true"` on a column. The built-in summaries depend on th
115
123
 
116
124
  ### Custom summary operands
117
125
 
118
- Extend `IgbNumberSummaryOperand` (or `IgbDateSummaryOperand`, `IgbSummaryOperand`) and override `Operate()` to return `IgbSummaryResult[]`. Apply via `Summaries` parameter:
119
-
120
- ```razor
121
- <IgbColumn Field="Salary" Header="Salary" HasSummary="true"
122
- Summaries="typeof(MySalarySummary)" />
123
- ```
126
+ Custom summaries in Blazor are implemented via JavaScript using `ColumnInitScript`. Define a JavaScript class with an `operate(data, allData, fieldName)` method that returns an array of `{ key, label, summaryResult }` objects, then assign it during column initialization.
124
127
 
125
- > For full custom summary class syntax, call `get_doc(framework: "blazor", slug: "grids/grid/summaries")` and use `get_api_reference` for the exact API contract.
128
+ > For full custom summary class syntax, call `get_doc(framework: "blazor", name: "grid-summaries")` for the JavaScript pattern and template usage.
126
129
 
127
130
  ### Summary position
128
131
 
@@ -227,11 +230,15 @@ The grid toolbar provides built-in UI for column hiding, column pinning, exporti
227
230
 
228
231
  ### Programmatic export
229
232
 
230
- ```razor
231
- @inject IgbExcelExporterService ExcelExporter
232
- @inject IgbCsvExporterService CsvExporter
233
+ Use a `@ref` on the `IgbGridToolbarExporter` to trigger export from code:
233
234
 
235
+ ```razor
234
236
  <IgbGrid @ref="grid" Data="data" PrimaryKey="Id">
237
+ <IgbGridToolbar>
238
+ <IgbGridToolbarActions>
239
+ <IgbGridToolbarExporter @ref="exporter" ExportExcel="true" ExportCSV="true" Filename="employees" />
240
+ </IgbGridToolbarActions>
241
+ </IgbGridToolbar>
235
242
  ...
236
243
  </IgbGrid>
237
244
 
@@ -240,40 +247,72 @@ The grid toolbar provides built-in UI for column hiding, column pinning, exporti
240
247
 
241
248
  @code {
242
249
  private IgbGrid grid = default!;
250
+ private IgbGridToolbarExporter exporter = default!;
243
251
 
244
252
  private async Task ExportToExcel()
245
253
  {
246
- var options = new IgbExcelExporterOptions("employees");
247
- await ExcelExporter.ExportAsync(grid, options);
254
+ await exporter.ExportGridAsync(GridToolbarExporterType.Excel);
248
255
  }
249
256
 
250
257
  private async Task ExportToCsv()
251
258
  {
252
- var options = new IgbCsvExporterOptions("employees");
253
- options.FileType = CsvFileTypes.CSV;
254
- await CsvExporter.ExportAsync(grid, options);
259
+ await exporter.ExportGridAsync(GridToolbarExporterType.CSV);
255
260
  }
256
261
  }
257
262
  ```
258
263
 
264
+ ### Customize export via events
265
+
266
+ Handle `ToolbarExporting` on the grid to modify options or cancel the export:
267
+
268
+ ```razor
269
+ <IgbGrid Data="data" PrimaryKey="Id" ToolbarExportingScript="OnToolbarExporting">
270
+ <IgbGridToolbar>
271
+ <IgbGridToolbarActions>
272
+ <IgbGridToolbarExporter ExportExcel="true" ExportCSV="true" />
273
+ </IgbGridToolbarActions>
274
+ </IgbGridToolbar>
275
+ ...
276
+ </IgbGrid>
277
+ ```
278
+
279
+ ```javascript
280
+ // In JavaScript
281
+ igRegisterScript("OnToolbarExporting", (evt) => {
282
+ const args = evt.detail;
283
+ args.options.fileName = `Report_${new Date().toDateString()}`;
284
+ // args.cancel = true; // to cancel export
285
+ args.exporter.columnExporting.subscribe((colArgs) => {
286
+ if (colArgs.header === "ID") {
287
+ colArgs.cancel = true; // skip this column
288
+ }
289
+ });
290
+ }, false);
291
+ ```
292
+
259
293
  ### Export options
260
294
 
295
+ These properties exist on `IgbExporterOptionsBase`, accessible via the `ToolbarExporting` event args:
296
+
261
297
  | Option | Type | Description |
262
298
  |---|---|---|
263
299
  | `FileName` | `string` | Name of the exported file (without extension) |
264
300
  | `IgnoreFiltering` | `bool` | Export all data, not just filtered |
265
301
  | `IgnoreSorting` | `bool` | Export in original data order |
266
302
  | `IgnoreColumnsVisibility` | `bool` | Include hidden columns in export |
267
- | `ExportGroupedRows` | `bool` | Include group rows in export (IgbGrid only) |
303
+ | `IgnoreGrouping` | `bool` | Ignore grouping in export (IgbGrid only) |
304
+ | `AlwaysExportHeaders` | `bool` | Export headers even if there is no data |
305
+ | `ExportSummaries` | `bool` | Include column summaries in export |
268
306
 
269
307
  ### Export events
270
308
 
271
- | Event | Description |
272
- |---|---|
273
- | `ExportStarted` | Fires before export begins - cancel or configure here |
274
- | `ExportEnded` | Fires after export completes |
275
- | `ColumnExporting` | Fires for each column - skip or modify |
276
- | `RowExporting` | Fires for each row - skip or modify |
309
+ | Event | On | Description |
310
+ |---|---|---|
311
+ | `ExportStarted` | `IgbGridToolbarExporter` | Fires before export begins |
312
+ | `ExportEnded` | `IgbGridToolbarExporter` | Fires after export completes |
313
+ | `ToolbarExporting` | Grid (`IgbGrid` etc.) | Fires when toolbar export is triggered - configure options or cancel |
314
+ | `ColumnExporting` | `IgbBaseExporter` (via event args) | Fires for each column - skip or modify |
315
+ | `RowExporting` | `IgbBaseExporter` (via event args) | Fires for each row - skip or modify |
277
316
 
278
317
  ---
279
318
 
@@ -324,14 +363,14 @@ Enable row reordering or drag-to-external targets:
324
363
 
325
364
  ```razor
326
365
  <IgbGrid Data="data" PrimaryKey="Id" RowDraggable="true">
327
- <DragGhostTemplate>
366
+ <DragGhostCustomTemplate>
328
367
  @{
329
368
  var row = (IgbGridRowDragGhostContext)context;
330
369
  }
331
370
  <div class="custom-ghost">
332
- Moving: @row.RowData
371
+ Moving: @row.Data
333
372
  </div>
334
- </DragGhostTemplate>
373
+ </DragGhostCustomTemplate>
335
374
  ...
336
375
  </IgbGrid>
337
376
  ```
@@ -385,7 +424,8 @@ Show a detail view for each expanded row. This is specific to the flat grid - fo
385
424
  <IgbColumn Field="Country" Header="Country" />
386
425
  <DetailTemplate>
387
426
  @{
388
- var customer = (Customer)context;
427
+ var ctx = (IgbGridMasterDetailContext)context;
428
+ var customer = (Customer)ctx.Implicit;
389
429
  }
390
430
  <div style="padding: 16px;">
391
431
  <h4>Orders for @customer.Name</h4>
@@ -33,17 +33,17 @@ The grid does not have built-in paging. Instead, place an `IgbPaginator` compone
33
33
 
34
34
  | Parameter | Type | Default | Description |
35
35
  |---|---|---|---|
36
- | `PerPage` | `int` | `15` | Rows per page |
37
- | `TotalRecords` | `int` | - | Total record count (required for remote paging) |
38
- | `SelectOptions` | `int[]` | `[5, 10, 15, 25, 50]` | Page size dropdown options |
36
+ | `PerPage` | `double` | `15` | Rows per page |
37
+ | `TotalRecords` | `double` | - | Total record count (required for remote paging) |
38
+ | `SelectOptions` | `double[]` | `[5, 10, 15, 25, 50]` | Page size dropdown options |
39
39
 
40
40
  ### Paginator events
41
41
 
42
42
  | Event | Type | Description |
43
43
  |---|---|---|
44
- | `PerPageChanged` | `EventCallback<int>` | Fires when page size changes |
45
- | `PageChanged` | `EventCallback<int>` | Fires when current page changes |
46
- | `PagingDone` | `EventCallback<IgbPagingEventArgs>` | Fires after paging completes |
44
+ | `PerPageChange` | `EventCallback<IgbNumberEventArgs>` | Fires when page size changes |
45
+ | `PageChange` | `EventCallback<IgbNumberEventArgs>` | Fires when current page changes |
46
+ | `PagingDone` | `EventCallback<IgbPageEventArgs>` | Fires after paging completes |
47
47
 
48
48
  ### Programmatic paging
49
49
 
@@ -76,7 +76,7 @@ The grid does not have built-in paging. Instead, place an `IgbPaginator` compone
76
76
 
77
77
  | Method | Description |
78
78
  |---|---|
79
- | `PaginateAsync(int page)` | Go to a specific page (0-based index) |
79
+ | `PaginateAsync(double page)` | Go to a specific page (0-based index) |
80
80
  | `NextPageAsync()` | Go to the next page |
81
81
  | `PreviousPageAsync()` | Go to the previous page |
82
82
 
@@ -94,8 +94,8 @@ When data lives on a server, fetch only the current page:
94
94
  <IgbColumn Field="Department" Header="Department" />
95
95
  <IgbPaginator PerPage="@pageSize"
96
96
  TotalRecords="@totalRecords"
97
- PageChanged="OnPageChanged"
98
- PerPageChanged="OnPerPageChanged" />
97
+ PageChange="OnPageChange"
98
+ PerPageChange="OnPerPageChange" />
99
99
  </IgbGrid>
100
100
 
101
101
  @code {
@@ -110,15 +110,15 @@ When data lives on a server, fetch only the current page:
110
110
  await LoadPageAsync();
111
111
  }
112
112
 
113
- private async Task OnPageChanged(int page)
113
+ private async Task OnPageChange(IgbNumberEventArgs args)
114
114
  {
115
- currentPage = page;
115
+ currentPage = (int)args.Detail;
116
116
  await LoadPageAsync();
117
117
  }
118
118
 
119
- private async Task OnPerPageChanged(int newPageSize)
119
+ private async Task OnPerPageChange(IgbNumberEventArgs args)
120
120
  {
121
- pageSize = newPageSize;
121
+ pageSize = (int)args.Detail;
122
122
  currentPage = 0;
123
123
  await LoadPageAsync();
124
124
  }
@@ -137,7 +137,7 @@ When data lives on a server, fetch only the current page:
137
137
 
138
138
  1. **Set `TotalRecords`** on the paginator - this tells it the total number of records on the server.
139
139
  2. **Bind `Data` to the current page** - only the current page's data is in memory.
140
- 3. **Handle `PageChanged` and `PerPageChanged`** - fetch new data from the server on each event.
140
+ 3. **Handle `PageChange` and `PerPageChange`** - fetch new data from the server on each event.
141
141
 
142
142
  ---
143
143
 
@@ -154,7 +154,7 @@ For large datasets, disable client-side sorting/filtering and handle them on the
154
154
  <IgbColumn Field="Department" Sortable="true" />
155
155
  <IgbColumn Field="Salary" Sortable="true" DataType="GridColumnDataType.Number" />
156
156
  <IgbPaginator PerPage="@pageSize" TotalRecords="@totalRecords"
157
- PageChanged="OnPageChanged" />
157
+ PageChange="OnPageChange" />
158
158
  </IgbGrid>
159
159
 
160
160
  @code {
@@ -165,16 +165,16 @@ For large datasets, disable client-side sorting/filtering and handle them on the
165
165
  private int currentPage = 0;
166
166
  private IgbSortingExpression[]? currentSort;
167
167
 
168
- private async Task OnSortingDone(IgbSortingEventArgs args)
168
+ private async Task OnSortingDone(IgbSortingExpressionEventArgs args)
169
169
  {
170
- currentSort = args.SortingExpressions;
170
+ currentSort = args.Detail;
171
171
  currentPage = 0;
172
172
  await LoadDataAsync();
173
173
  }
174
174
 
175
- private async Task OnPageChanged(int page)
175
+ private async Task OnPageChange(IgbNumberEventArgs args)
176
176
  {
177
- currentPage = page;
177
+ currentPage = (int)args.Detail;
178
178
  await LoadDataAsync();
179
179
  }
180
180
 
@@ -207,11 +207,11 @@ For large datasets, disable client-side sorting/filtering and handle them on the
207
207
  private IgbGrid grid = default!;
208
208
  private List<Employee> data = new();
209
209
 
210
- private async Task OnFilteringDone(IgbFilteringEventArgs args)
210
+ private async Task OnFilteringDone(IgbFilteringExpressionsTreeEventArgs args)
211
211
  {
212
212
  // Extract filter information and send to server
213
- var filterExpressions = args.FilteringExpressions;
214
- var result = await Api.GetEmployeesFilteredAsync(filterExpressions);
213
+ var filterDetail = args.Detail;
214
+ var result = await Api.GetEmployeesFilteredAsync(filterDetail);
215
215
  data = result.Items;
216
216
  StateHasChanged();
217
217
  }
@@ -291,7 +291,7 @@ With 50 columns at 150px each (7500px total) in an 800px wide grid, only the vis
291
291
 
292
292
  1. **`IgbPaginator` goes inside the grid** - it is a child component, not a sibling.
293
293
  2. **Remote paging requires `TotalRecords`** - without it, the paginator cannot calculate page count.
294
- 3. **Handle events for remote operations** - `SortingDone`, `FilteringDone`, `PageChanged` are your hooks to fetch server data.
294
+ 3. **Handle events for remote operations** - `SortingDone`, `FilteringDone`, `PageChange` are your hooks to fetch server data.
295
295
  4. **Virtualization needs a fixed `Height`** - this is the #1 performance requirement.
296
296
  5. **Do not use `.Skip().Take()` on `IQueryable` directly on the grid** - the grid expects a materialized collection (`List<T>` or `T[]`). Fetch data asynchronously and set it as the `Data` property.
297
297
  6. **`StateHasChanged()` after data updates** - call it after reassigning the `Data` property from an async operation.
@@ -146,21 +146,24 @@ Users can drag column borders to resize. Combine with `MinWidth` and `MaxWidth`
146
146
 
147
147
  ### Auto-size column to fit content
148
148
 
149
- Programmatically auto-size a column to fit its longest cell value:
149
+ Programmatically auto-size a column to fit its longest visible cell value:
150
150
 
151
151
  ```razor
152
152
  @code {
153
153
  private IgbGrid grid = default!;
154
154
 
155
- private async Task AutoSizeNameColumn()
155
+ private void AutoSizeNameColumn()
156
156
  {
157
157
  var column = grid.GetColumnByName("Name");
158
- await grid.AutoSizeColumnWidthAsync(column);
158
+ column.Autosize(false); // false = include cell content, true = header only
159
159
  }
160
160
 
161
- private async Task AutoSizeAllColumns()
161
+ private void AutoSizeAllColumns()
162
162
  {
163
- await grid.AutoSizeColumnsWidthAsync();
163
+ foreach (var col in grid.Columns)
164
+ {
165
+ col.Autosize(false);
166
+ }
164
167
  }
165
168
  }
166
169
  ```
@@ -168,10 +171,10 @@ Programmatically auto-size a column to fit its longest cell value:
168
171
  ### Column auto-width on init
169
172
 
170
173
  ```razor
171
- <IgbColumn Field="Name" Header="Name" AutoSize="true" />
174
+ <IgbColumn Field="Name" Header="Name" Width="auto" />
172
175
  ```
173
176
 
174
- When `AutoSize="true"`, the column width adjusts on initial render to fit the header and visible content.
177
+ When `Width="auto"`, the column width adjusts on initial render to fit the header and visible content.
175
178
 
176
179
  ---
177
180
 
@@ -179,19 +182,19 @@ When `AutoSize="true"`, the column width adjusts on initial render to fit the he
179
182
 
180
183
  ### Default row height
181
184
 
182
- The default row height depends on the theme's display density. Use `DisplayDensity` on the grid:
185
+ The default row height depends on the `--ig-size` CSS custom property. Set it on the grid or a parent element:
183
186
 
184
- ```razor
185
- <IgbGrid Data="data" PrimaryKey="Id" DisplayDensity="DisplayDensity.Comfortable">
186
- ...
187
- </IgbGrid>
187
+ ```css
188
+ igc-grid {
189
+ --ig-size: var(--ig-size-large); /* default */
190
+ }
188
191
  ```
189
192
 
190
- | Display Density | Approximate Row Height |
193
+ | `--ig-size` value | Approximate Row Height |
191
194
  |---|---|
192
- | `Comfortable` | 50px (default) |
193
- | `Cosy` | 40px |
194
- | `Compact` | 32px |
195
+ | `var(--ig-size-large)` | 50px (default) |
196
+ | `var(--ig-size-medium)` | 40px |
197
+ | `var(--ig-size-small)` | 32px |
195
198
 
196
199
  ### Custom row height
197
200
 
@@ -215,22 +218,11 @@ Or use `RowHeight` parameter:
215
218
 
216
219
  ## Cell Spacing (CSS Variables)
217
220
 
218
- Control cell padding and spacing using CSS custom properties:
219
-
220
- ```css
221
- igc-grid {
222
- --ig-grid-cell-padding-block: 12px; /* top and bottom padding */
223
- --ig-grid-cell-padding-inline: 16px; /* left and right padding */
224
- }
225
- ```
226
-
227
- ### Available CSS variables for grid spacing
221
+ The grid does not expose individual cell-padding CSS custom properties. Cell padding and row height are controlled by the `--ig-size` CSS variable:
228
222
 
229
223
  | CSS Variable | Description | Default |
230
224
  |---|---|---|
231
- | `--ig-grid-cell-padding-block` | Vertical cell padding | Theme-dependent |
232
- | `--ig-grid-cell-padding-inline` | Horizontal cell padding | Theme-dependent |
233
- | `--ig-size` | Overall component size (affects row height, cell padding) | `var(--ig-size-large)` |
225
+ | `--ig-size` | Overall component size (affects row height, cell padding, header height) | `var(--ig-size-large)` |
234
226
 
235
227
  ### Sizing via `--ig-size`
236
228
 
@@ -280,5 +272,5 @@ Apply different sizing to a specific grid:
280
272
  5. **`MinWidth` and `MaxWidth` constrain resizing** - always set them when `Resizable="true"` for predictable UX.
281
273
  6. **`--ig-size` controls the overall density** - it affects row height, cell padding, header height, and internal spacing.
282
274
  7. **Column virtualization requires column widths** - without widths, the grid cannot calculate which columns are outside the viewport.
283
- 8. **Auto-size is a one-time operation** - `AutoSize="true"` on a column fits content at initial render; it doesn't update dynamically as data changes.
275
+ 8. **Auto-size is a one-time operation** - `Width="auto"` on a column fits content at initial render; it doesn't update dynamically as data changes.
284
276
  9. **Row height consistency** - all rows in a grid have the same height. Variable row height is not supported.
@@ -21,6 +21,7 @@ Save and restore the full grid state (sorting, filtering, grouping, paging, sele
21
21
 
22
22
  <IgbGrid @ref="grid" Data="data" PrimaryKey="Id" AutoGenerate="false"
23
23
  Width="100%" Height="500px">
24
+ <IgbGridState @ref="gridState"></IgbGridState>
24
25
  <IgbColumn Field="Name" Sortable="true" Filterable="true" />
25
26
  <IgbColumn Field="Department" Sortable="true" Groupable="true" />
26
27
  <IgbColumn Field="Salary" DataType="GridColumnDataType.Currency" HasSummary="true" />
@@ -32,11 +33,11 @@ Save and restore the full grid state (sorting, filtering, grouping, paging, sele
32
33
 
33
34
  @code {
34
35
  private IgbGrid grid = default!;
36
+ private IgbGridState gridState = default!;
35
37
 
36
38
  private async Task SaveState()
37
39
  {
38
- var state = await grid.GetStateAsync();
39
- var json = state.ToJson();
40
+ string json = await gridState.GetStateAsStringAsync(new string[0]);
40
41
  await JS.InvokeVoidAsync("localStorage.setItem", "gridState", json);
41
42
  }
42
43
 
@@ -45,8 +46,7 @@ Save and restore the full grid state (sorting, filtering, grouping, paging, sele
45
46
  var json = await JS.InvokeAsync<string>("localStorage.getItem", "gridState");
46
47
  if (!string.IsNullOrEmpty(json))
47
48
  {
48
- var state = IgbGridState.FromJson(json);
49
- await grid.SetStateAsync(state);
49
+ await gridState.ApplyStateFromStringAsync(json, new string[0]);
50
50
  }
51
51
  }
52
52
  }
@@ -69,40 +69,39 @@ Save and restore the full grid state (sorting, filtering, grouping, paging, sele
69
69
  ### Auto-save on navigation
70
70
 
71
71
  ```razor
72
- @implements IAsyncDisposable
72
+ @implements IDisposable
73
73
 
74
- <IgbGrid @ref="grid" Data="data" PrimaryKey="Id">
74
+ <IgbGrid @ref="grid" Data="data" PrimaryKey="Id" Rendered="OnGridRendered">
75
+ <IgbGridState @ref="gridState"></IgbGridState>
75
76
  ...
76
77
  </IgbGrid>
77
78
 
78
79
  @code {
79
80
  private IgbGrid grid = default!;
81
+ private IgbGridState gridState = default!;
80
82
 
81
- protected override async Task OnAfterRenderAsync(bool firstRender)
83
+ void OnGridRendered()
82
84
  {
83
- if (firstRender)
84
- {
85
- await RestoreState();
86
- }
85
+ RestoreGridState();
87
86
  }
88
87
 
89
- public async ValueTask DisposeAsync()
88
+ void IDisposable.Dispose()
90
89
  {
91
- await SaveState();
90
+ SaveGridState();
92
91
  }
93
92
 
94
- private async Task SaveState()
93
+ async void SaveGridState()
95
94
  {
96
- var state = await grid.GetStateAsync();
97
- await JS.InvokeVoidAsync("localStorage.setItem", "gridState", state.ToJson());
95
+ string state = await gridState.GetStateAsStringAsync(new string[0]);
96
+ await JS.InvokeVoidAsync("localStorage.setItem", "gridState", state);
98
97
  }
99
98
 
100
- private async Task RestoreState()
99
+ async void RestoreGridState()
101
100
  {
102
- var json = await JS.InvokeAsync<string>("localStorage.getItem", "gridState");
103
- if (!string.IsNullOrEmpty(json))
101
+ string state = await JS.InvokeAsync<string>("localStorage.getItem", "gridState");
102
+ if (!string.IsNullOrEmpty(state))
104
103
  {
105
- await grid.SetStateAsync(IgbGridState.FromJson(json));
104
+ await gridState.ApplyStateFromStringAsync(state, new string[0]);
106
105
  }
107
106
  }
108
107
  }
@@ -110,21 +109,33 @@ Save and restore the full grid state (sorting, filtering, grouping, paging, sele
110
109
 
111
110
  ### Selective state save/restore
112
111
 
113
- Save only specific parts of the state:
112
+ Save only specific parts of the state by passing feature name strings:
114
113
 
115
114
  ```razor
116
115
  @code {
116
+ private IgbGridState gridState = default!;
117
+
117
118
  private async Task SaveSortingOnly()
118
119
  {
119
- var state = await grid.GetStateAsync(new IgbGridStateOptions
120
+ string state = await gridState.GetStateAsStringAsync(new string[] { "sorting" });
121
+ await JS.InvokeVoidAsync("localStorage.setItem", "gridSorting", state);
122
+ }
123
+ }
124
+ ```
125
+
126
+ To disable specific features from being tracked, set `Options` on the `IgbGridState` component:
127
+
128
+ ```razor
129
+ @code {
130
+ private IgbGridState gridState = default!;
131
+
132
+ protected override void OnInitialized()
133
+ {
134
+ gridState.Options = new IgbGridStateOptions
120
135
  {
121
- Sorting = true,
122
- Filtering = false,
123
- Paging = false,
124
- Selection = false,
125
- Columns = false
126
- });
127
- await JS.InvokeVoidAsync("localStorage.setItem", "gridSorting", state.ToJson());
136
+ CellSelection = false,
137
+ Sorting = false
138
+ };
128
139
  }
129
140
  }
130
141
  ```
@@ -133,10 +144,11 @@ Save only specific parts of the state:
133
144
 
134
145
  ```razor
135
146
  @code {
147
+ private IgbGridState gridState = default!;
148
+
136
149
  private async Task SaveToServer()
137
150
  {
138
- var state = await grid.GetStateAsync();
139
- var json = state.ToJson();
151
+ string json = await gridState.GetStateAsStringAsync(new string[0]);
140
152
  await UserPreferencesApi.SaveGridStateAsync(userId, "employeesGrid", json);
141
153
  }
142
154
 
@@ -145,7 +157,7 @@ Save only specific parts of the state:
145
157
  var json = await UserPreferencesApi.GetGridStateAsync(userId, "employeesGrid");
146
158
  if (!string.IsNullOrEmpty(json))
147
159
  {
148
- await grid.SetStateAsync(IgbGridState.FromJson(json));
160
+ await gridState.ApplyStateFromStringAsync(json, new string[0]);
149
161
  }
150
162
  }
151
163
  }
@@ -156,5 +168,6 @@ Save only specific parts of the state:
156
168
  ## Key Rules
157
169
 
158
170
  1. **`PrimaryKey` must be set on the grid** for state persistence to work reliably (especially for selection and row pinning).
159
- 2. **State serialization is JSON** - `GetStateAsync()` returns an object that can be serialized with `ToJson()`.
160
- 3. **Restore state in `OnAfterRenderAsync`** - the grid must be rendered before you can call `SetStateAsync`.
171
+ 2. **`IgbGridState` is a child component of the grid** - add `<IgbGridState @ref="gridState">` inside the grid markup and use its methods.
172
+ 3. **Use `GetStateAsStringAsync` / `ApplyStateFromStringAsync`** - these accept/return JSON strings directly. Pass `new string[0]` for all features, or specific feature names like `new string[] { "sorting", "filtering" }`.
173
+ 4. **Restore state in the grid's `Rendered` event** - the grid must be fully rendered before you can call `ApplyStateFromStringAsync`.