0
# Table Components
1
2
Specialized components for building feature-rich, sortable tables with column management and customizable rendering.
3
4
## Capabilities
5
6
### Column Component
7
8
Describes the header and cell contents of a table column, defining how data should be displayed and processed.
9
10
```javascript { .api }
11
/**
12
* Table column descriptor component
13
* @param props - Column configuration
14
*/
15
function Column(props: {
16
/** Aria label for column header */
17
'aria-label'?: string;
18
/** Function to extract cell data from row data */
19
cellDataGetter?: (params: {columnData: any, dataKey: string, rowData: any}) => any;
20
/** Function to render cell content */
21
cellRenderer?: (params: {cellData: any, columnData: any, dataKey: string, rowData: any, rowIndex: number}) => React.Node;
22
/** Optional CSS class for cells */
23
className?: string;
24
/** Additional data passed to cell renderers */
25
columnData?: object;
26
/** Key to identify the data field */
27
dataKey: any;
28
/** Default sort direction when first clicked */
29
defaultSortDirection?: 'ASC' | 'DESC';
30
/** Disable sorting for this column */
31
disableSort?: boolean;
32
/** Flex grow factor */
33
flexGrow?: number;
34
/** Flex shrink factor */
35
flexShrink?: number;
36
/** Function to render column header */
37
headerRenderer?: (params: {columnData: any, dataKey: string, disableSort: boolean, label: any, sortBy: string, sortDirection: string}) => React.Node;
38
/** Optional header CSS class */
39
headerClassName?: string;
40
/** Header inline style */
41
headerStyle?: object;
42
/** Optional element ID */
43
id?: string;
44
/** Column header label */
45
label?: any;
46
/** Maximum column width */
47
maxWidth?: number;
48
/** Minimum column width */
49
minWidth?: number;
50
/** Optional inline style for cells */
51
style?: object;
52
/** Fixed column width */
53
width: number;
54
}): React.Component;
55
```
56
57
**Usage Examples:**
58
59
```javascript
60
import React from 'react';
61
import { Table, Column } from 'react-virtualized';
62
63
// Basic table with custom column renderers
64
function UserTable({ users, onSort, sortBy, sortDirection }) {
65
const rowGetter = ({ index }) => users[index];
66
67
// Custom avatar renderer
68
const avatarRenderer = ({ cellData, rowData }) => (
69
<div className="avatar-cell">
70
<img
71
src={cellData || '/default-avatar.png'}
72
alt={`${rowData.name} avatar`}
73
className="user-avatar"
74
/>
75
</div>
76
);
77
78
// Custom status renderer with badges
79
const statusRenderer = ({ cellData }) => (
80
<span className={`status-badge status-${cellData.toLowerCase()}`}>
81
{cellData}
82
</span>
83
);
84
85
// Custom actions renderer
86
const actionsRenderer = ({ rowData, rowIndex }) => (
87
<div className="actions-cell">
88
<button onClick={() => editUser(rowData.id)}>Edit</button>
89
<button onClick={() => deleteUser(rowData.id)}>Delete</button>
90
</div>
91
);
92
93
// Custom header with tooltip
94
const headerWithTooltip = ({ label, dataKey, sortBy, sortDirection }) => (
95
<div className="header-with-tooltip" title={`Click to sort by ${label}`}>
96
{label}
97
{sortBy === dataKey && (
98
<span className="sort-indicator">
99
{sortDirection === 'ASC' ? ' ▲' : ' ▼'}
100
</span>
101
)}
102
</div>
103
);
104
105
return (
106
<Table
107
width={900}
108
height={400}
109
headerHeight={50}
110
rowHeight={60}
111
rowCount={users.length}
112
rowGetter={rowGetter}
113
sort={onSort}
114
sortBy={sortBy}
115
sortDirection={sortDirection}
116
>
117
<Column
118
label="Avatar"
119
dataKey="avatarUrl"
120
width={80}
121
cellRenderer={avatarRenderer}
122
disableSort={true}
123
headerRenderer={headerWithTooltip}
124
/>
125
<Column
126
label="Name"
127
dataKey="name"
128
width={200}
129
flexGrow={1}
130
headerRenderer={headerWithTooltip}
131
/>
132
<Column
133
label="Email"
134
dataKey="email"
135
width={250}
136
headerRenderer={headerWithTooltip}
137
/>
138
<Column
139
label="Status"
140
dataKey="status"
141
width={100}
142
cellRenderer={statusRenderer}
143
headerRenderer={headerWithTooltip}
144
/>
145
<Column
146
label="Actions"
147
dataKey="actions"
148
width={120}
149
cellRenderer={actionsRenderer}
150
disableSort={true}
151
/>
152
</Table>
153
);
154
}
155
156
// Advanced table with custom data getters
157
function SalesTable({ salesData }) {
158
const rowGetter = ({ index }) => salesData[index];
159
160
// Custom data getter for calculated fields
161
const totalSalesGetter = ({ rowData }) => {
162
return rowData.q1Sales + rowData.q2Sales + rowData.q3Sales + rowData.q4Sales;
163
};
164
165
// Custom data getter for formatting
166
const formattedDateGetter = ({ rowData, dataKey }) => {
167
const date = new Date(rowData[dataKey]);
168
return date.toLocaleDateString();
169
};
170
171
// Currency formatter
172
const currencyRenderer = ({ cellData }) => (
173
<span className="currency">
174
${cellData.toLocaleString()}
175
</span>
176
);
177
178
// Performance indicator
179
const performanceRenderer = ({ cellData }) => {
180
const percentage = cellData * 100;
181
const className = percentage >= 100 ? 'over-target' : 'under-target';
182
183
return (
184
<div className={`performance-indicator ${className}`}>
185
<div className="performance-bar">
186
<div
187
className="performance-fill"
188
style={{ width: `${Math.min(percentage, 100)}%` }}
189
/>
190
</div>
191
<span>{percentage.toFixed(1)}%</span>
192
</div>
193
);
194
};
195
196
return (
197
<Table
198
width={1000}
199
height={500}
200
headerHeight={40}
201
rowHeight={50}
202
rowCount={salesData.length}
203
rowGetter={rowGetter}
204
>
205
<Column
206
label="Sales Rep"
207
dataKey="name"
208
width={150}
209
/>
210
<Column
211
label="Start Date"
212
dataKey="startDate"
213
width={120}
214
cellDataGetter={formattedDateGetter}
215
/>
216
<Column
217
label="Q1 Sales"
218
dataKey="q1Sales"
219
width={100}
220
cellRenderer={currencyRenderer}
221
/>
222
<Column
223
label="Q2 Sales"
224
dataKey="q2Sales"
225
width={100}
226
cellRenderer={currencyRenderer}
227
/>
228
<Column
229
label="Q3 Sales"
230
dataKey="q3Sales"
231
width={100}
232
cellRenderer={currencyRenderer}
233
/>
234
<Column
235
label="Q4 Sales"
236
dataKey="q4Sales"
237
width={100}
238
cellRenderer={currencyRenderer}
239
/>
240
<Column
241
label="Total Sales"
242
dataKey="totalSales"
243
width={120}
244
cellDataGetter={totalSalesGetter}
245
cellRenderer={currencyRenderer}
246
/>
247
<Column
248
label="vs Target"
249
dataKey="performanceRatio"
250
width={150}
251
cellRenderer={performanceRenderer}
252
/>
253
</Table>
254
);
255
}
256
```
257
258
### SortDirection Constants
259
260
Constants for table sort directions, used with sortable columns.
261
262
```javascript { .api }
263
/**
264
* Sort direction constants
265
*/
266
const SortDirection = {
267
/** Sort items in ascending order (a-z, 0-9) */
268
ASC: 'ASC',
269
/** Sort items in descending order (z-a, 9-0) */
270
DESC: 'DESC'
271
};
272
```
273
274
**Usage Examples:**
275
276
```javascript
277
import React, { useState } from 'react';
278
import { Table, Column, SortDirection } from 'react-virtualized';
279
280
function SortableTable({ data }) {
281
const [sortBy, setSortBy] = useState('name');
282
const [sortDirection, setSortDirection] = useState(SortDirection.ASC);
283
const [sortedData, setSortedData] = useState(data);
284
285
const sort = ({ sortBy: newSortBy, sortDirection: newSortDirection }) => {
286
const sorted = [...data].sort((a, b) => {
287
const aVal = a[newSortBy];
288
const bVal = b[newSortBy];
289
290
let result = 0;
291
if (aVal < bVal) result = -1;
292
else if (aVal > bVal) result = 1;
293
294
return newSortDirection === SortDirection.DESC ? -result : result;
295
});
296
297
setSortBy(newSortBy);
298
setSortDirection(newSortDirection);
299
setSortedData(sorted);
300
};
301
302
const rowGetter = ({ index }) => sortedData[index];
303
304
return (
305
<Table
306
width={600}
307
height={400}
308
headerHeight={50}
309
rowHeight={40}
310
rowCount={sortedData.length}
311
rowGetter={rowGetter}
312
sort={sort}
313
sortBy={sortBy}
314
sortDirection={sortDirection}
315
>
316
<Column
317
label="Name"
318
dataKey="name"
319
width={200}
320
defaultSortDirection={SortDirection.ASC}
321
/>
322
<Column
323
label="Age"
324
dataKey="age"
325
width={100}
326
defaultSortDirection={SortDirection.DESC}
327
/>
328
<Column
329
label="Score"
330
dataKey="score"
331
width={100}
332
defaultSortDirection={SortDirection.DESC}
333
/>
334
</Table>
335
);
336
}
337
```
338
339
### SortIndicator Component
340
341
Visual indicator component for showing sort direction in table headers.
342
343
```javascript { .api }
344
/**
345
* Sort indicator component
346
* @param props - SortIndicator configuration
347
*/
348
function SortIndicator(props: {
349
/** Current sort direction */
350
sortDirection?: 'ASC' | 'DESC';
351
}): React.Component;
352
```
353
354
**Usage Examples:**
355
356
```javascript
357
import React from 'react';
358
import { SortIndicator, SortDirection } from 'react-virtualized';
359
360
// Custom header renderer with SortIndicator
361
function CustomHeaderRenderer({ label, sortBy, sortDirection, dataKey }) {
362
const showSortIndicator = sortBy === dataKey;
363
364
return (
365
<div className="custom-header">
366
<span className="header-label">{label}</span>
367
{showSortIndicator && (
368
<SortIndicator sortDirection={sortDirection} />
369
)}
370
</div>
371
);
372
}
373
374
// Table with custom sort indicators
375
function TableWithSortIndicators({ data, onSort, sortBy, sortDirection }) {
376
const rowGetter = ({ index }) => data[index];
377
378
return (
379
<Table
380
width={700}
381
height={400}
382
headerHeight={50}
383
rowHeight={40}
384
rowCount={data.length}
385
rowGetter={rowGetter}
386
sort={onSort}
387
sortBy={sortBy}
388
sortDirection={sortDirection}
389
headerStyle={{ fontWeight: 'bold' }}
390
>
391
<Column
392
label="Product Name"
393
dataKey="name"
394
width={250}
395
headerRenderer={CustomHeaderRenderer}
396
/>
397
<Column
398
label="Price"
399
dataKey="price"
400
width={100}
401
headerRenderer={CustomHeaderRenderer}
402
cellRenderer={({ cellData }) => `$${cellData.toFixed(2)}`}
403
/>
404
<Column
405
label="Stock"
406
dataKey="stock"
407
width={80}
408
headerRenderer={CustomHeaderRenderer}
409
/>
410
<Column
411
label="Rating"
412
dataKey="rating"
413
width={100}
414
headerRenderer={CustomHeaderRenderer}
415
cellRenderer={({ cellData }) => (
416
<div className="rating">
417
{'★'.repeat(Math.floor(cellData))}
418
{'☆'.repeat(5 - Math.floor(cellData))}
419
<span className="rating-value">{cellData.toFixed(1)}</span>
420
</div>
421
)}
422
/>
423
</Table>
424
);
425
}
426
```
427
428
### Default Table Renderers
429
430
Built-in rendering functions for common table functionality.
431
432
```javascript { .api }
433
/**
434
* Default cell data getter - extracts data from row object
435
*/
436
function defaultTableCellDataGetter(params: {
437
columnData: any,
438
dataKey: string,
439
rowData: any
440
}): any;
441
442
/**
443
* Default cell renderer - renders cell data as text
444
*/
445
function defaultTableCellRenderer(params: {
446
cellData: any,
447
columnData: any,
448
dataKey: string,
449
rowData: any,
450
rowIndex: number
451
}): React.Node;
452
453
/**
454
* Default header renderer - renders column header with sort indicators
455
*/
456
function defaultTableHeaderRenderer(params: {
457
columnData: any,
458
dataKey: string,
459
disableSort: boolean,
460
label: any,
461
sortBy: string,
462
sortDirection: string
463
}): React.Node;
464
465
/**
466
* Default header row renderer - renders the entire header row
467
*/
468
function defaultTableHeaderRowRenderer(params: {
469
className: string,
470
columns: React.Node[],
471
style: object
472
}): React.Node;
473
474
/**
475
* Default row renderer - renders an entire table row
476
*/
477
function defaultTableRowRenderer(params: {
478
className: string,
479
columns: React.Node[],
480
index: number,
481
key: string,
482
onRowClick?: (params: {event: Event, index: number, rowData: object}) => void,
483
onRowDoubleClick?: (params: {event: Event, index: number, rowData: object}) => void,
484
onRowMouseOut?: (params: {event: Event, index: number, rowData: object}) => void,
485
onRowMouseOver?: (params: {event: Event, index: number, rowData: object}) => void,
486
onRowRightClick?: (params: {event: Event, index: number, rowData: object}) => void,
487
rowData: object,
488
style: object
489
}): React.Node;
490
491
/**
492
* Multi-column sort utility
493
*/
494
function createTableMultiSort(
495
sortFunction: (params: {sortBy: string, sortDirection: string}) => void,
496
options?: {
497
defaultSortBy?: Array<string>,
498
defaultSortDirection?: {[key: string]: string}
499
}
500
): (params: {event: Event, sortBy: string, sortDirection: string}) => void;
501
```
502
503
**Usage Examples:**
504
505
```javascript
506
import React from 'react';
507
import {
508
Table,
509
Column,
510
createTableMultiSort,
511
defaultTableRowRenderer
512
} from 'react-virtualized';
513
514
// Table with multi-column sorting
515
function MultiSortTable({ data }) {
516
const [sortBy, setSortBy] = useState(['name']);
517
const [sortDirection, setSortDirection] = useState({ name: 'ASC' });
518
519
const multiSort = createTableMultiSort(
520
({ sortBy, sortDirection }) => {
521
// Custom multi-sort logic here
522
console.log('Multi-sort:', sortBy, sortDirection);
523
},
524
{
525
defaultSortBy: ['name', 'age'],
526
defaultSortDirection: { name: 'ASC', age: 'DESC' }
527
}
528
);
529
530
// Custom row renderer with hover effects
531
const customRowRenderer = (props) => {
532
return (
533
<div
534
{...props}
535
className={`${props.className} custom-row`}
536
style={{
537
...props.style,
538
cursor: 'pointer'
539
}}
540
onMouseEnter={() => console.log('Row hovered:', props.index)}
541
>
542
{props.columns}
543
</div>
544
);
545
};
546
547
const rowGetter = ({ index }) => data[index];
548
549
return (
550
<Table
551
width={800}
552
height={400}
553
headerHeight={50}
554
rowHeight={45}
555
rowCount={data.length}
556
rowGetter={rowGetter}
557
rowRenderer={customRowRenderer}
558
onHeaderClick={multiSort}
559
>
560
<Column label="Name" dataKey="name" width={200} />
561
<Column label="Age" dataKey="age" width={100} />
562
<Column label="Department" dataKey="department" width={150} />
563
<Column label="Salary" dataKey="salary" width={120} />
564
</Table>
565
);
566
}
567
```