0
# Row Features
1
2
Row-level functionality including selection, expansion, grouping, pagination, and row pinning. These features provide comprehensive row management capabilities for interactive table experiences.
3
4
## Capabilities
5
6
### Row Selection
7
8
Multi-row and single-row selection with hierarchical selection support for nested data.
9
10
```typescript { .api }
11
/** Row selection state mapping row IDs to selection status */
12
type RowSelectionState = Record<string, boolean>;
13
14
interface RowSelectionOptions<TData extends RowData> {
15
/** Row selection change handler */
16
onRowSelectionChange?: OnChangeFn<RowSelectionState>;
17
/** Enable row selection globally */
18
enableRowSelection?: boolean | ((row: Row<TData>) => boolean);
19
/** Enable multi-row selection */
20
enableMultiRowSelection?: boolean | ((row: Row<TData>) => boolean);
21
/** Enable sub-row selection */
22
enableSubRowSelection?: boolean | ((row: Row<TData>) => boolean);
23
/** Enable manual row selection mode */
24
manualRowSelection?: boolean;
25
/** Auto reset selection when data changes */
26
autoResetRowSelection?: boolean;
27
}
28
29
interface RowSelectionInstance<TData extends RowData> {
30
/** Get current row selection state */
31
getState(): { rowSelection: RowSelectionState };
32
/** Set row selection state */
33
setRowSelection(updater: Updater<RowSelectionState>): void;
34
/** Reset row selection to initial state */
35
resetRowSelection(defaultState?: boolean): void;
36
/** Get whether all rows are selected */
37
getIsAllRowsSelected(): boolean;
38
/** Get whether some rows are selected */
39
getIsSomeRowsSelected(): boolean;
40
/** Get whether all page rows are selected */
41
getIsAllPageRowsSelected(): boolean;
42
/** Get whether some page rows are selected */
43
getIsSomePageRowsSelected(): boolean;
44
/** Toggle all rows selection */
45
toggleAllRowsSelected(value?: boolean): void;
46
/** Toggle all page rows selection */
47
toggleAllPageRowsSelected(value?: boolean): void;
48
/** Get selected row model */
49
getSelectedRowModel(): RowModel<TData>;
50
/** Get filtered selected row model */
51
getFilteredSelectedRowModel(): RowModel<TData>;
52
/** Get grouped selected row model */
53
getGroupedSelectedRowModel(): RowModel<TData>;
54
}
55
```
56
57
**Usage Examples:**
58
59
```typescript
60
import { createTable } from "@tanstack/table-core";
61
62
// Basic row selection
63
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
64
65
const table = createTable({
66
data,
67
columns,
68
getCoreRowModel: getCoreRowModel(),
69
onRowSelectionChange: setRowSelection,
70
state: {
71
rowSelection,
72
},
73
enableRowSelection: true,
74
enableMultiRowSelection: true,
75
});
76
77
// Conditional row selection
78
const table = createTable({
79
data,
80
columns,
81
getCoreRowModel: getCoreRowModel(),
82
enableRowSelection: (row) => row.original.status !== 'disabled',
83
enableMultiRowSelection: true,
84
});
85
86
// Selection management
87
const selectedRows = table.getSelectedRowModel().rows;
88
const isAllSelected = table.getIsAllRowsSelected();
89
table.toggleAllRowsSelected();
90
91
// Individual row selection
92
const firstRow = table.getRowModel().rows[0];
93
firstRow.toggleSelected();
94
const isSelected = firstRow.getIsSelected();
95
```
96
97
### Row Selection Row Methods
98
99
Methods available on individual rows for selection management.
100
101
```typescript { .api }
102
interface RowSelectionRow {
103
/** Get whether this row is selected */
104
getIsSelected(): boolean;
105
/** Get whether this row can be selected */
106
getCanSelect(): boolean;
107
/** Get whether this row can multi-select */
108
getCanMultiSelect(): boolean;
109
/** Get whether this row can select sub-rows */
110
getCanSelectSubRows(): boolean;
111
/** Toggle selection of this row */
112
toggleSelected(value?: boolean): void;
113
/** Get selection percentage for partially selected groups */
114
getIsAllSubRowsSelected(): boolean;
115
/** Get whether some sub-rows are selected */
116
getIsSomeSelected(): boolean;
117
}
118
```
119
120
### Row Selection Utilities
121
122
Utility functions for managing row selection state and logic.
123
124
```typescript { .api }
125
/**
126
* Utility function for selecting rows
127
* @param rows - Array of rows to process
128
* @param rowSelection - Current selection state
129
* @returns Updated selection state
130
*/
131
function selectRowsFn<TData extends RowData>(
132
rows: Row<TData>[],
133
rowSelection: RowSelectionState
134
): RowSelectionState;
135
136
/**
137
* Check if a row is selected
138
* @param row - Row to check
139
* @param selection - Selection state
140
* @returns Whether row is selected
141
*/
142
function isRowSelected<TData extends RowData>(
143
row: Row<TData>,
144
selection: RowSelectionState
145
): boolean;
146
147
/**
148
* Check if a sub-row is selected
149
* @param row - Parent row to check
150
* @param selection - Selection state
151
* @returns Whether sub-row is selected
152
*/
153
function isSubRowSelected<TData extends RowData>(
154
row: Row<TData>,
155
selection: RowSelectionState
156
): boolean;
157
```
158
159
### Row Expanding
160
161
Expand and collapse rows with hierarchical data support and custom expansion logic.
162
163
```typescript { .api }
164
/** Expanded state mapping row IDs to expansion status */
165
type ExpandedState = Record<string, boolean>;
166
167
/** Alternative expanded state as array of row IDs */
168
type ExpandedStateList = string[];
169
170
interface ExpandedOptions<TData extends RowData> {
171
/** Expanded state change handler */
172
onExpandedChange?: OnChangeFn<ExpandedState>;
173
/** Auto reset expanded state when data changes */
174
autoResetExpanded?: boolean;
175
/** Enable expanding rows */
176
enableExpanding?: boolean;
177
/** Get sub-rows for a given row */
178
getSubRows?: (originalRow: TData, index: number) => TData[] | undefined;
179
/** Get whether a row can expand */
180
getCanExpand?: (row: Row<TData>) => boolean;
181
/** Get expanded row model */
182
getExpandedRowModel?: () => RowModel<TData>;
183
/** Get whether row is expanded by default */
184
getIsRowExpanded?: (row: Row<TData>) => boolean;
185
/** Manual expanding mode */
186
manualExpanding?: boolean;
187
/** Maximum expansion depth */
188
maxLeafRowFilterDepth?: number;
189
/** Filter from leafs up */
190
filterFromLeafRows?: boolean;
191
}
192
193
interface ExpandedInstance<TData extends RowData> {
194
/** Get current expanded state */
195
getState(): { expanded: ExpandedState };
196
/** Set expanded state */
197
setExpanded(updater: Updater<ExpandedState>): void;
198
/** Reset expanded state */
199
resetExpanded(defaultState?: boolean): void;
200
/** Get whether all rows are expanded */
201
getIsAllRowsExpanded(): boolean;
202
/** Get whether some rows are expanded */
203
getIsSomeRowsExpanded(): boolean;
204
/** Toggle all rows expansion */
205
toggleAllRowsExpanded(expanded?: boolean): void;
206
/** Get pre-expanded row model */
207
getPreExpandedRowModel(): RowModel<TData>;
208
/** Get expanded row model */
209
getExpandedRowModel(): RowModel<TData>;
210
}
211
```
212
213
**Usage Examples:**
214
215
```typescript
216
// Row expanding setup
217
const [expanded, setExpanded] = useState<ExpandedState>({});
218
219
const table = createTable({
220
data: hierarchicalData,
221
columns,
222
getCoreRowModel: getCoreRowModel(),
223
getExpandedRowModel: getExpandedRowModel(),
224
onExpandedChange: setExpanded,
225
state: {
226
expanded,
227
},
228
getSubRows: (originalRow) => originalRow.subRows,
229
});
230
231
// Expand/collapse rows
232
const row = table.getRowModel().rows[0];
233
row.toggleExpanded();
234
const isExpanded = row.getIsExpanded();
235
const canExpand = row.getCanExpand();
236
237
// Expand all rows
238
table.toggleAllRowsExpanded(true);
239
```
240
241
### Row Expanding Row Methods
242
243
Methods available on individual rows for expansion management.
244
245
```typescript { .api }
246
interface ExpandedRow {
247
/** Get whether this row is expanded */
248
getIsExpanded(): boolean;
249
/** Get whether this row can expand */
250
getCanExpand(): boolean;
251
/** Toggle expansion of this row */
252
toggleExpanded(expanded?: boolean): void;
253
/** Get toggle handler for this row */
254
getToggleExpandedHandler(): () => void;
255
}
256
```
257
258
### Row Grouping
259
260
Group rows by column values with aggregation support and nested grouping.
261
262
```typescript { .api }
263
/** Grouping state as array of column IDs to group by */
264
type GroupingState = string[];
265
266
/** Grouping column mode */
267
type GroupingColumnMode = false | 'reorder' | 'remove';
268
269
interface GroupingOptions {
270
/** Grouping state change handler */
271
onGroupingChange?: OnChangeFn<GroupingState>;
272
/** Auto reset grouping when data changes */
273
autoResetGrouping?: boolean;
274
/** Enable grouping globally */
275
enableGrouping?: boolean;
276
/** Get grouped row model */
277
getGroupedRowModel?: () => RowModel<TData>;
278
/** Manual grouping mode */
279
manualGrouping?: boolean;
280
/** Group expanded state */
281
groupedColumnMode?: GroupingColumnMode;
282
}
283
284
interface GroupingInstance<TData extends RowData> {
285
/** Get current grouping state */
286
getState(): { grouping: GroupingState };
287
/** Set grouping state */
288
setGrouping(updater: Updater<GroupingState>): void;
289
/** Reset grouping state */
290
resetGrouping(defaultState?: boolean): void;
291
/** Get pre-grouped row model */
292
getPreGroupedRowModel(): RowModel<TData>;
293
/** Get grouped row model */
294
getGroupedRowModel(): RowModel<TData>;
295
}
296
```
297
298
**Usage Examples:**
299
300
```typescript
301
import { getGroupedRowModel } from "@tanstack/table-core";
302
303
// Row grouping setup
304
const [grouping, setGrouping] = useState<GroupingState>([]);
305
306
const table = createTable({
307
data,
308
columns,
309
getCoreRowModel: getCoreRowModel(),
310
getGroupedRowModel: getGroupedRowModel(),
311
onGroupingChange: setGrouping,
312
state: {
313
grouping,
314
},
315
enableGrouping: true,
316
});
317
318
// Group by columns
319
table.setGrouping(['department', 'role']);
320
321
// Column-level grouping methods
322
const deptColumn = table.getColumn('department');
323
deptColumn.toggleGrouping();
324
const groupingIndex = deptColumn.getGroupedIndex();
325
```
326
327
### Row Pagination
328
329
Paginate large datasets with customizable page sizes and navigation.
330
331
```typescript { .api }
332
/** Pagination state */
333
interface PaginationState {
334
pageIndex: number;
335
pageSize: number;
336
}
337
338
interface PaginationOptions {
339
/** Pagination state change handler */
340
onPaginationChange?: OnChangeFn<PaginationState>;
341
/** Auto reset pagination when data changes */
342
autoResetPageIndex?: boolean;
343
/** Enable manual pagination mode */
344
manualPagination?: boolean;
345
/** Get paginated row model */
346
getPaginationRowModel?: () => RowModel<TData>;
347
/** Total row count for manual pagination */
348
rowCount?: number;
349
/** Page count for manual pagination */
350
pageCount?: number;
351
}
352
353
interface PaginationInstance<TData extends RowData> {
354
/** Get current pagination state */
355
getState(): { pagination: PaginationState };
356
/** Set pagination state */
357
setPagination(updater: Updater<PaginationState>): void;
358
/** Reset pagination state */
359
resetPagination(defaultState?: boolean): void;
360
/** Set page index */
361
setPageIndex(updater: Updater<number>): void;
362
/** Reset page index */
363
resetPageIndex(defaultState?: boolean): void;
364
/** Set page size */
365
setPageSize(updater: Updater<number>): void;
366
/** Reset page size */
367
resetPageSize(defaultState?: boolean): void;
368
/** Get page count */
369
getPageCount(): number;
370
/** Get row count */
371
getRowCount(): number;
372
/** Get pre-paginated row model */
373
getPrePaginationRowModel(): RowModel<TData>;
374
/** Get paginated row model */
375
getPaginationRowModel(): RowModel<TData>;
376
/** Get current page */
377
getPage(): Row<TData>[];
378
/** Get whether can go to previous page */
379
getCanPreviousPage(): boolean;
380
/** Get whether can go to next page */
381
getCanNextPage(): boolean;
382
/** Go to previous page */
383
previousPage(): void;
384
/** Go to next page */
385
nextPage(): void;
386
/** Get first page */
387
firstPage(): void;
388
/** Get last page */
389
lastPage(): void;
390
/** Get page options */
391
getPageOptions(): number[];
392
}
393
```
394
395
**Usage Examples:**
396
397
```typescript
398
import { getPaginationRowModel } from "@tanstack/table-core";
399
400
// Pagination setup
401
const [pagination, setPagination] = useState<PaginationState>({
402
pageIndex: 0,
403
pageSize: 10,
404
});
405
406
const table = createTable({
407
data,
408
columns,
409
getCoreRowModel: getCoreRowModel(),
410
getPaginationRowModel: getPaginationRowModel(),
411
onPaginationChange: setPagination,
412
state: {
413
pagination,
414
},
415
});
416
417
// Pagination controls
418
const canPrevious = table.getCanPreviousPage();
419
const canNext = table.getCanNextPage();
420
const pageCount = table.getPageCount();
421
const currentPage = table.getState().pagination.pageIndex + 1;
422
423
// Navigation
424
table.previousPage();
425
table.nextPage();
426
table.setPageIndex(0);
427
table.setPageSize(25);
428
```
429
430
### Row Pinning
431
432
Pin specific rows to the top or bottom of the table.
433
434
```typescript { .api }
435
/** Row pinning position */
436
type RowPinningPosition = 'top' | 'bottom' | false;
437
438
/** Row pinning state */
439
interface RowPinningState {
440
top?: string[];
441
bottom?: string[];
442
}
443
444
interface RowPinningOptions<TData extends RowData> {
445
/** Row pinning change handler */
446
onRowPinningChange?: OnChangeFn<RowPinningState>;
447
/** Enable row pinning globally */
448
enableRowPinning?: boolean | ((row: Row<TData>) => boolean);
449
/** Keep pinned rows */
450
keepPinnedRows?: boolean;
451
/** Auto reset row pinning when data changes */
452
autoResetRowPinning?: boolean;
453
}
454
455
interface RowPinningInstance<TData extends RowData> {
456
/** Get current row pinning state */
457
getState(): { rowPinning: RowPinningState };
458
/** Set row pinning state */
459
setRowPinning(updater: Updater<RowPinningState>): void;
460
/** Reset row pinning state */
461
resetRowPinning(defaultState?: boolean): void;
462
/** Get whether any rows are pinned */
463
getIsSomeRowsPinned(position?: RowPinningPosition): boolean;
464
/** Get top pinned rows */
465
getTopRows(): Row<TData>[];
466
/** Get bottom pinned rows */
467
getBottomRows(): Row<TData>[];
468
/** Get center (unpinned) rows */
469
getCenterRows(): Row<TData>[];
470
}
471
```
472
473
**Usage Examples:**
474
475
```typescript
476
// Row pinning setup
477
const [rowPinning, setRowPinning] = useState<RowPinningState>({
478
top: [],
479
bottom: [],
480
});
481
482
const table = createTable({
483
data,
484
columns,
485
getCoreRowModel: getCoreRowModel(),
486
onRowPinningChange: setRowPinning,
487
state: {
488
rowPinning,
489
},
490
enableRowPinning: true,
491
});
492
493
// Pin/unpin rows
494
const row = table.getRowModel().rows[0];
495
row.pin('top');
496
row.pin('bottom');
497
row.pin(false); // Unpin
498
499
// Get pinned rows
500
const topRows = table.getTopRows();
501
const centerRows = table.getCenterRows();
502
const bottomRows = table.getBottomRows();
503
```
504
505
### Row Pinning Row Methods
506
507
Methods available on individual rows for pinning management.
508
509
```typescript { .api }
510
interface RowPinningRow {
511
/** Get current pin position of this row */
512
getIsPinned(): RowPinningPosition;
513
/** Get pin index of this row */
514
getPinnedIndex(): number;
515
/** Get whether this row can be pinned */
516
getCanPin(): boolean;
517
/** Pin this row to specified position */
518
pin(position: RowPinningPosition): void;
519
}
520
```
521
522
### Row Extension Interfaces
523
524
Row extensions for each feature providing additional methods and properties.
525
526
```typescript { .api }
527
interface VisibilityRow<TData extends RowData> {
528
/** Get visible cells for this row */
529
getVisibleCells(): Cell<TData, unknown>[];
530
}
531
532
interface ColumnPinningRow<TData extends RowData> {
533
/** Get left pinned cells */
534
getLeftVisibleCells(): Cell<TData, unknown>[];
535
/** Get center cells */
536
getCenterVisibleCells(): Cell<TData, unknown>[];
537
/** Get right pinned cells */
538
getRightVisibleCells(): Cell<TData, unknown>[];
539
}
540
541
interface ColumnFiltersRow<TData extends RowData> {
542
/** Column filters don't add row methods */
543
}
544
545
interface GroupingRow {
546
/** Get grouping value for this row */
547
getGroupingValue(columnId: string): unknown;
548
/** Get whether this is a grouped row */
549
getIsGrouped(): boolean;
550
/** Get group level */
551
groupingColumnId?: string;
552
/** Get group value */
553
groupingValue?: unknown;
554
}
555
```
556
557
**Usage Examples:**
558
559
```typescript
560
// Working with row extensions
561
const row = table.getRowModel().rows[0];
562
563
// Visibility
564
const visibleCells = row.getVisibleCells();
565
566
// Pinning
567
const leftCells = row.getLeftVisibleCells();
568
const centerCells = row.getCenterVisibleCells();
569
const rightCells = row.getRightVisibleCells();
570
571
// Selection
572
const isSelected = row.getIsSelected();
573
row.toggleSelected();
574
575
// Expansion
576
const isExpanded = row.getIsExpanded();
577
row.toggleExpanded();
578
579
// Grouping
580
if (row.getIsGrouped()) {
581
console.log('Group value:', row.groupingValue);
582
console.log('Group column:', row.groupingColumnId);
583
}
584
585
// Pinning
586
const pinPosition = row.getIsPinned();
587
if (pinPosition) {
588
console.log(`Row is pinned to ${pinPosition}`);
589
}
590
```