Persisting the Selection
The Grid enables you to persist the selection state and maintain full control over which rows or cells are selected by using the built-in SelectionDirective.
The following example demonstrates a comprehensive approach to persist row selection in the Grid. This includes programmatic selection and selection across paging, sorting, and filtering.
To enable selection persistence, apply the built-in SelectionDirective to the Grid and set the selectedKeys property to a collection of items that define which rows or cells are selected. This directive enables you to:
- Select rows or cells programmatically from your component code.
- Maintain selection across paging (virtual scrolling), sorting, and other data operations.
- Specify initially selected items when the Grid loads.
- Update the selection dynamically based on your business logic.
- Control selection with any unique identifier from your data.
Persisting Row Selection
To persist the selected rows in the Grid, set the selectedKeys property of the SelectionDirective to an array of keys that identify the selected rows. You can choose from three strategies to define these keys:
Using Data Item Field
To persist selection reliably across data operations, set the kendoGridSelectBy property to a unique field from your data items—typically an ID field.
<kendo-grid kendoGridSelectBy="id" [selectedKeys]="[1,3,5]" ...></kendo-grid>
The following example demonstrates how to persist selection by the id field and select rows programmatically.
This approach is recommended for most production scenarios. It maintains selection across paging, sorting, filtering, and programmatic updates.
You can use this approach in e-commerce product catalogs, CRM customer records, and order management systems. Use it in any scenario where each row has a unique identifier like ProductID, OrderID, or CustomerID.
Using Row Index
By default, the SelectionDirective stores selected items by their absolute row index.
<kendo-grid kendoGridSelectBy [selectedKeys]="[0,3,4]" ...></kendo-grid>
Data operations like sorting and filtering change the row data while indices remain the same. This may cause the selection to shift to different rows.
The following example demonstrates how the row selection persists during page changes.
Use this approach for simple scenarios such as:
- Prototypes with static data.
- Read-only datasets without sorting or filtering.
- Specific row positions you need to target.
For applications with dynamic data, use a unique field as the Using Data Item Field shows.
Using Custom Key
For advanced scenarios, the kendoGridSelectBy property accepts a function. This function receives a RowArgs parameter and returns the key to use for that row.
<kendo-grid
[kendoGridSelectBy]="customKey"
[selectedKeys]="['value1-value2']"
...>
</kendo-grid>The following example demonstrates how to persist selection with a custom key function.
Use this approach when your unique identifier requires complex logic:
- Composite primary keys (for example,
orderId-lineItemId,tenantId-recordId). - Multi-location data (for example,
warehouseId-productId). - Versioned documents (for example,
documentId-version). - Time-series data (for example,
sensorId-timestamp). - Legacy systems with non-standard identifiers.
Persisting Cell Selection
To persist the selected cells in the Grid, set the selectedKeys property of the SelectionDirective to an array of keys that identify the selected cells. You can choose from three strategies to define these keys:
Using Data Item and Column Fields
To persist cell selection reliably across data operations, set the kendoGridSelectBy property to a unique field for row identification and the columnKey property for column identification.
<kendo-grid
kendoGridSelectBy="id"
[columnKey]="'field'"
[selectedKeys]="[{itemKey: 1, columnKey: 'customerName'}]"
...>
</kendo-grid>
The following example demonstrates how to store selected cells with the id field for rows and the column field property for columns.
This approach is recommended for most production scenarios. It maintains cell selection across paging, sorting, filtering, column reordering, and programmatic updates.
You can use this approach in spreadsheet-like applications, data entry forms, and financial reporting tools. Use it in any scenario where you need to track specific cell selections by their data and column identifiers.
Using Row and Column Indices
When cell selection is enabled, by default, the SelectionDirective stores selected cells by their absolute rowIndex and colIndex.
The following example demonstrates the default behavior when you enable cell selection.
Use this approach for simple scenarios such as:
- Prototypes with static data.
- Read-only datasets without sorting, filtering, or column reordering.
- Specific cell positions you need to target.
Data operations like sorting, filtering, or column reordering change the cell data while indices remain the same. This causes the selection to shift to different cells.
For applications with dynamic data or column management, use data item and column fields as the next section shows.
Using Custom Keys
For advanced scenarios, the kendoGridSelectBy and columnKey properties accept functions that return custom keys for rows and columns.
<kendo-grid
[kendoGridSelectBy]="myRowSelectionKey"
[columnKey]="myColSelectionKey"
[selectedKeys]="mySelection"
...>
</kendo-grid>The following example demonstrates how to store cell selection with custom key functions.
Use this approach when your unique identifier requires complex logic:
- Composite keys for rows or columns.
- Dynamic column configurations.
- Conditional identification based on cell content or state.
Selecting All Rows
You can extend the select-all checkbox functionality to select all Grid rows when paging or virtual scrolling is used.
The following example demonstrates how to select all Grid rows when virtual scrolling is enabled.
The same approach applies when paging is used.
To select Grid when paging or virtual scrolling is enabled, follow these steps:
-
Create a custom checkbox in the column header and apply the
SelectAllCheckboxDirectivedirective. Then, handle theselectAllChangeevent:html<ng-template kendoGridHeaderTemplate> <kendo-checkbox kendoGridSelectAllCheckbox [state]="selectAllState" (selectAllChange)="onSelectAllChange($event)" ></kendo-checkbox> </ng-template> -
Update the
selectedKeyscollection in theselectAllChangeevent handler:tspublic onSelectAllChange(checkedState: SelectAllCheckboxState): void { if (checkedState === 'checked') { this.mySelection = this.items.map((item) => item.id); this.selectAllState = 'checked'; } else { this.mySelection = []; this.selectAllState = 'unchecked'; } } -
Control the checkbox state using the
stateproperty and theselectedKeysChangeevent of theSelectionDirective:tspublic onSelectedKeysChange(): void { const len = this.mySelection.length; if (len === 0) { this.selectAllState = 'unchecked'; } else if (len > 0 && len < this.items.length) { this.selectAllState = 'indeterminate'; } else { this.selectAllState = 'checked'; } }
Persisting Range Selection with Virtual Scrolling
You can persist range selection in the Grid when virtual scrolling is enabled. To achieve this, you need to handle the selectionChange and cellClick events to implement Shift + Click range selection and Ctrl/Cmd + Click toggle selection.
The following example demonstrates how to persist range selection with virtual scrolling.
When you enable virtual scrolling or paging, the Grid renders items from the current page only. To maintain selection as users scroll through virtual content:
-
Set
kendoGridSelectByto your unique field and bindselectedKeysto track selections. To support keyboard selection shortcuts, you must handle theselectionChangeandcellClickevents.html<kendo-grid kendoGridSelectBy="id" [selectedKeys]="selectedKeys" (selectionChange)="onSelectionChange($event)" (cellClick)="onCellClick($event)"> </kendo-grid> -
In the
selectionChangeevent handler, use therangeStartRowandrangeEndRowproperties of theSelectionEventto implementShift + Clickrange selection.tspublic onSelectionChange(e: SelectionEvent): void { if (e.shiftKey && e.rangeStartRow && e.rangeEndRow) { const startId = e.rangeStartRow.dataItem.id; const endId = e.rangeEndRow.dataItem.id; const [start, end] = startId < endId ? [startId, endId] : [endId, startId]; this.selectedKeys = this.data .filter(item => item.id >= start && item.id <= end) .map(item => item.id); } } -
In the same
selectionChangeevent handler, use thectrlKeyproperty to implementCtrl/Cmd + Clicktoggle selection.tselse if (e.ctrlKey) { const keysToAdd = e.selectedRows.map(row => row.dataItem.id); const keysToRemove = e.deselectedRows.map(row => row.dataItem.id); this.selectedKeys = [ ...this.selectedKeys.filter(key => !keysToRemove.includes(key)), ...keysToAdd ]; } -
Handle simple clicks without modifier keys in the
cellClickevent.tspublic onCellClick(e: CellClickEvent): void { const { ctrlKey, metaKey, shiftKey } = e.originalEvent; if (!ctrlKey && !metaKey && !shiftKey) { this.selectedKeys = [e.dataItem.id]; } }