@insticc/react-datagrid-2 1.1.20 → 1.1.22
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.
- package/README.md +2084 -1042
- package/build/index.js +10 -4
- package/build/wrapper/index.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,1042 +1,2084 @@
|
|
|
1
|
-
# DataGrid Component
|
|
2
|
-
|
|
3
|
-
A powerful and flexible React data grid component built on top of Material React Table, providing advanced features for data visualization, filtering, sorting, pagination, and row selection.
|
|
4
|
-
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [Installation](#installation)
|
|
8
|
-
- [Basic Usage](#basic-usage)
|
|
9
|
-
- [Props Reference](#props-reference)
|
|
10
|
-
- [Core Props](#core-props)
|
|
11
|
-
- [Column Configuration](#column-configuration)
|
|
12
|
-
- [Actions & Toolbar](#actions--toolbar)
|
|
13
|
-
- [Export Options](#export-options)
|
|
14
|
-
- [Selection & Interaction](#selection--interaction)
|
|
15
|
-
- [Pagination & Display](#pagination--display)
|
|
16
|
-
- [Styling & Layout](#styling--layout)
|
|
17
|
-
- [Advanced Features](#advanced-features)
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
20
|
-
- [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
{
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- **
|
|
124
|
-
- **
|
|
125
|
-
- **Example:**
|
|
126
|
-
```jsx
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
#### `
|
|
139
|
-
- **Type:** `
|
|
140
|
-
- **
|
|
141
|
-
- **
|
|
142
|
-
- **Example:**
|
|
143
|
-
```jsx
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
- **
|
|
258
|
-
- **
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
- `
|
|
269
|
-
- `
|
|
270
|
-
-
|
|
271
|
-
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
- **
|
|
284
|
-
- **
|
|
285
|
-
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
-
|
|
289
|
-
-
|
|
290
|
-
-
|
|
291
|
-
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
-
|
|
297
|
-
-
|
|
298
|
-
-
|
|
299
|
-
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
- **
|
|
346
|
-
- **
|
|
347
|
-
- **
|
|
348
|
-
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
- **
|
|
381
|
-
- **
|
|
382
|
-
- **
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
- **
|
|
391
|
-
- **
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
- **
|
|
402
|
-
- **
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
- **
|
|
407
|
-
- **
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
- **
|
|
437
|
-
- **
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
- **
|
|
442
|
-
- **
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
- **
|
|
462
|
-
- **
|
|
463
|
-
- **
|
|
464
|
-
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
- **
|
|
469
|
-
- **
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
#### `
|
|
476
|
-
- **Type:** `
|
|
477
|
-
- **
|
|
478
|
-
- **
|
|
479
|
-
- **Example:**
|
|
480
|
-
```jsx
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
- `
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
- `
|
|
500
|
-
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
- `
|
|
516
|
-
- `
|
|
517
|
-
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
```
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
When
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
};
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
**
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
**
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1
|
+
# DataGrid Component
|
|
2
|
+
|
|
3
|
+
A powerful and flexible React data grid component built on top of Material React Table, providing advanced features for data visualization, filtering, sorting, pagination, and row selection.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Basic Usage](#basic-usage)
|
|
9
|
+
- [Props Reference](#props-reference)
|
|
10
|
+
- [Core Props](#core-props)
|
|
11
|
+
- [Column Configuration](#column-configuration)
|
|
12
|
+
- [Actions & Toolbar](#actions--toolbar)
|
|
13
|
+
- [Export Options](#export-options)
|
|
14
|
+
- [Selection & Interaction](#selection--interaction)
|
|
15
|
+
- [Pagination & Display](#pagination--display)
|
|
16
|
+
- [Styling & Layout](#styling--layout)
|
|
17
|
+
- [Advanced Features](#advanced-features)
|
|
18
|
+
- [Cache & Updates](#cache--updates)
|
|
19
|
+
- [Callbacks](#callbacks)
|
|
20
|
+
- [Column Types](#column-types)
|
|
21
|
+
- [Examples](#examples)
|
|
22
|
+
- [API Reference](#api-reference)
|
|
23
|
+
- [Performance Tips](#performance-tips)
|
|
24
|
+
- [Browser Support](#browser-support)
|
|
25
|
+
- [Troubleshooting](#troubleshooting)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @insticc/react-datagrid-2
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Required Dependencies
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install react prop-types material-react-table semantic-ui-react @mui/material @mui/x-date-pickers date-fns bootstrap semantic-ui-css
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Basic Usage
|
|
44
|
+
|
|
45
|
+
```jsx
|
|
46
|
+
import React, { useState } from 'react';
|
|
47
|
+
import { DataGrid } from '@insticc/react-datagrid-2';
|
|
48
|
+
|
|
49
|
+
function MyComponent() {
|
|
50
|
+
const [selectedRows, setSelectedRows] = useState([]);
|
|
51
|
+
|
|
52
|
+
const columns = [
|
|
53
|
+
{ accessorKey: 'id', header: 'ID', type: 'text' },
|
|
54
|
+
{ accessorKey: 'name', header: 'Name', type: 'text' },
|
|
55
|
+
{ accessorKey: 'email', header: 'Email', type: 'email' },
|
|
56
|
+
{ accessorKey: 'createdAt', header: 'Created', type: 'date', isDateColumn: true },
|
|
57
|
+
];
|
|
58
|
+
|
|
59
|
+
const data = [
|
|
60
|
+
{ id: '1', name: 'John Doe', email: 'john@example.com', createdAt: '2025-01-15' },
|
|
61
|
+
{ id: '2', name: 'Jane Smith', email: 'jane@example.com', createdAt: '2025-02-20' },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<DataGrid
|
|
66
|
+
columns={columns}
|
|
67
|
+
createRows={data}
|
|
68
|
+
rowKey="id"
|
|
69
|
+
selectData={setSelectedRows}
|
|
70
|
+
hasExcelExport={true}
|
|
71
|
+
hasPdfExport={true}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Props Reference
|
|
80
|
+
|
|
81
|
+
### Core Props
|
|
82
|
+
|
|
83
|
+
#### `columns` (required)
|
|
84
|
+
- **Type:** `Array<ColumnDefinition>`
|
|
85
|
+
- **Description:** Array of column definitions that determine how data is displayed
|
|
86
|
+
- **Example:**
|
|
87
|
+
```jsx
|
|
88
|
+
const columns = [
|
|
89
|
+
{
|
|
90
|
+
accessorKey: 'name', // Key to access data (use with accessorFn or alone)
|
|
91
|
+
header: 'Full Name', // Column header text
|
|
92
|
+
type: 'text', // Cell type - formatter applied automatically
|
|
93
|
+
|
|
94
|
+
// Data Access
|
|
95
|
+
accessorFn: (row) => row.firstName + ' ' + row.lastName,
|
|
96
|
+
|
|
97
|
+
// Filtering & Sorting
|
|
98
|
+
enableSorting: true, // Enable/disable sorting (default: true)
|
|
99
|
+
enableColumnFilter: true, // Enable/disable filtering (default: true)
|
|
100
|
+
enableColumnFilterModes: true, // Allow changing filter modes (default: true)
|
|
101
|
+
filterFn: 'contains', // Filter function type (default: 'contains')
|
|
102
|
+
sortingFn: 'basic', // Sorting function (default: 'basic' or custom for dates)
|
|
103
|
+
isDateColumn: false, // Special handling for dates (default: false)
|
|
104
|
+
|
|
105
|
+
// Display
|
|
106
|
+
cellClass: 'custom-class', // CSS class wrapping cell content
|
|
107
|
+
Cell: CustomComponent, // Optional: Custom cell renderer (receives typeValue)
|
|
108
|
+
enableResizing: true, // Allow column resizing (default: true)
|
|
109
|
+
grow: true, // Column can grow (default: true)
|
|
110
|
+
enableClickToCopy: false, // Enable click-to-copy (default: false)
|
|
111
|
+
enableColumnActions: false, // Show column actions menu (default: false)
|
|
112
|
+
}
|
|
113
|
+
];
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Column Rendering Modes:**
|
|
117
|
+
- `type` only: Formatter applied automatically
|
|
118
|
+
- `type` + `cellClass`: Formatted content wrapped in div with CSS class
|
|
119
|
+
- `type` + `Cell`: Custom component receives `typeValue` (formatted content) as prop
|
|
120
|
+
- `Cell` only: Full custom rendering without type formatter
|
|
121
|
+
|
|
122
|
+
#### `createRows` (required)
|
|
123
|
+
- **Type:** `Array<Object>`
|
|
124
|
+
- **Description:** Array of data objects to display in the grid
|
|
125
|
+
- **Example:**
|
|
126
|
+
```jsx
|
|
127
|
+
const data = [
|
|
128
|
+
{ id: 1, name: 'John', email: 'john@example.com' },
|
|
129
|
+
{ id: 2, name: 'Jane', email: 'jane@example.com' }
|
|
130
|
+
];
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### `rowKey` (required)
|
|
134
|
+
- **Type:** `string`
|
|
135
|
+
- **Description:** Property name used as unique identifier for each row
|
|
136
|
+
- **Example:** `rowKey="id"` or `rowKey="uuid"`
|
|
137
|
+
|
|
138
|
+
#### `selectData` (required)
|
|
139
|
+
- **Type:** `function`
|
|
140
|
+
- **Description:** Callback function that receives selected rows whenever selection changes
|
|
141
|
+
- **Signature:** `(selectedRows: Array<Object>) => void`
|
|
142
|
+
- **Example:**
|
|
143
|
+
```jsx
|
|
144
|
+
const handleSelection = (rows) => {
|
|
145
|
+
console.log('Selected rows:', rows);
|
|
146
|
+
console.log('Selected IDs:', rows.map(r => r.id));
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
<DataGrid selectData={handleSelection} />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Column Configuration
|
|
155
|
+
|
|
156
|
+
#### Understanding `accessorKey` vs `accessorFn`
|
|
157
|
+
|
|
158
|
+
The DataGrid provides two ways to access data from your rows:
|
|
159
|
+
|
|
160
|
+
##### `accessorKey` (Simple Access)
|
|
161
|
+
- **Type:** `string`
|
|
162
|
+
- **Use when:** You want to access a property directly from the row object
|
|
163
|
+
- **Example:**
|
|
164
|
+
```jsx
|
|
165
|
+
{
|
|
166
|
+
accessorKey: 'name', // Accesses row.name
|
|
167
|
+
header: 'Name'
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
##### `accessorFn` (Custom Access)
|
|
172
|
+
- **Type:** `(row: Object) => any`
|
|
173
|
+
- **Use when:** You need to compute or transform the value from row data
|
|
174
|
+
- **Receives:** The complete row object as parameter
|
|
175
|
+
- **Returns:** The value to be used for display, filtering, and sorting
|
|
176
|
+
- **Priority:** Overrides `accessorKey` if both are defined
|
|
177
|
+
- **Examples:**
|
|
178
|
+
|
|
179
|
+
```jsx
|
|
180
|
+
// Example 1: Handle null/undefined values with fallback
|
|
181
|
+
{
|
|
182
|
+
accessorKey: 'acronym',
|
|
183
|
+
accessorFn: (row) => row.acronym ?? '',
|
|
184
|
+
header: 'Acronym',
|
|
185
|
+
type: 'text'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Example 2: Access nested object properties
|
|
189
|
+
{
|
|
190
|
+
accessorKey: 'paperCount',
|
|
191
|
+
accessorFn: (row) => row.numberPapers?.value ?? 0,
|
|
192
|
+
header: 'Papers',
|
|
193
|
+
type: 'integer'
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Example 3: Combine multiple fields
|
|
197
|
+
{
|
|
198
|
+
accessorKey: 'fullName',
|
|
199
|
+
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
|
|
200
|
+
header: 'Full Name',
|
|
201
|
+
type: 'text'
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Example 4: Conditional logic
|
|
205
|
+
{
|
|
206
|
+
accessorKey: 'status',
|
|
207
|
+
accessorFn: (row) => row.isActive ? 'Active' : 'Inactive',
|
|
208
|
+
header: 'Status',
|
|
209
|
+
type: 'text'
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Example 5: Complex calculations
|
|
213
|
+
{
|
|
214
|
+
accessorKey: 'total',
|
|
215
|
+
accessorFn: (row) => (row.price || 0) * (row.quantity || 0),
|
|
216
|
+
header: 'Total',
|
|
217
|
+
type: 'currency'
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Example 6: Array to string conversion
|
|
221
|
+
{
|
|
222
|
+
accessorKey: 'tags',
|
|
223
|
+
accessorFn: (row) => row.tags?.join(', ') ?? 'No tags',
|
|
224
|
+
header: 'Tags',
|
|
225
|
+
type: 'text'
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Example 7: Date formatting for sorting
|
|
229
|
+
{
|
|
230
|
+
accessorKey: 'createdDate',
|
|
231
|
+
accessorFn: (row) => row.createdAt ? new Date(row.createdAt).getTime() : 0,
|
|
232
|
+
header: 'Created',
|
|
233
|
+
type: 'date',
|
|
234
|
+
isDateColumn: true
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Important Notes:**
|
|
239
|
+
- `accessorFn` is executed for **every cell render, filter, and sort operation**
|
|
240
|
+
- Keep the function lightweight to avoid performance issues
|
|
241
|
+
- The returned value is what gets filtered and sorted (not the original cell display)
|
|
242
|
+
- When using `accessorFn`, you typically still need `accessorKey` as a unique identifier for the column
|
|
243
|
+
- `accessorFn` value is passed to the type formatter (if `type` is specified)
|
|
244
|
+
|
|
245
|
+
**Performance Tip:**
|
|
246
|
+
```jsx
|
|
247
|
+
// Bad - Creates new object every time
|
|
248
|
+
accessorFn: (row) => ({ value: row.data, label: row.name })
|
|
249
|
+
|
|
250
|
+
// Good - Returns simple value
|
|
251
|
+
accessorFn: (row) => row.data?.value ?? 0
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
#### `columnVisibilityState`
|
|
255
|
+
- **Type:** `object`
|
|
256
|
+
- **Default:** `{}`
|
|
257
|
+
- **Description:** Controls which columns are visible/hidden
|
|
258
|
+
- **Example:**
|
|
259
|
+
```jsx
|
|
260
|
+
columnVisibilityState={{
|
|
261
|
+
email: false, // Hide email column
|
|
262
|
+
phone: true, // Show phone column
|
|
263
|
+
id: false // Hide ID column
|
|
264
|
+
}}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
#### `columnOrder`
|
|
268
|
+
- **Type:** `Array<string>`
|
|
269
|
+
- **Default:** `[]`
|
|
270
|
+
- **Description:** Defines the order of columns by their accessorKey
|
|
271
|
+
- **Example:**
|
|
272
|
+
```jsx
|
|
273
|
+
columnOrder={['name', 'email', 'createdAt', 'id']}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
### Actions & Toolbar
|
|
279
|
+
|
|
280
|
+
#### `actions`
|
|
281
|
+
- **Type:** `Array<ActionObject>`
|
|
282
|
+
- **Default:** `null`
|
|
283
|
+
- **Description:** Array of custom action buttons displayed in the toolbar
|
|
284
|
+
- **Action Object Properties:**
|
|
285
|
+
- `name` (string): Button label
|
|
286
|
+
- `function` (function, required): Callback when button is clicked - receives selected rows or table instance
|
|
287
|
+
- `tooltip` (string): Tooltip text on hover
|
|
288
|
+
- `color` (string): Button color - one of: `'blue'`, `'red'`, `'green'`, `'yellow'`, `'orange'`, `'black'`, `'grey'`, `'teal'`, `'brown'`, `'violet'`, `'purple'`, `'olive'`, `'pink'`
|
|
289
|
+
- `icon` (string|element): Icon name (Semantic UI) or React element
|
|
290
|
+
- `selectionMode` (string): When button is enabled:
|
|
291
|
+
- `'single'` - Enabled only when exactly one row is selected
|
|
292
|
+
- `'multi'` - Enabled when one or more rows are selected
|
|
293
|
+
- `'always'` - Always enabled regardless of selection
|
|
294
|
+
- `confirmMessage` (string|element): Confirmation message before action executes
|
|
295
|
+
- `hasConfirmMessage` (boolean): Whether to show confirmation dialog
|
|
296
|
+
- `disabled` (boolean): Manually disable the button
|
|
297
|
+
- `visible` (boolean): Show/hide the button (default: true)
|
|
298
|
+
- `toggle` (boolean): Render as toggle button
|
|
299
|
+
- `active` (boolean): Toggle button active state (when toggle: true)
|
|
300
|
+
- `key` (string): Unique React key (defaults to name)
|
|
301
|
+
- **Example:**
|
|
302
|
+
```jsx
|
|
303
|
+
actions={[
|
|
304
|
+
{
|
|
305
|
+
name: 'Delete',
|
|
306
|
+
function: (selectedRows) => handleDelete(selectedRows),
|
|
307
|
+
tooltip: 'Delete selected rows',
|
|
308
|
+
color: 'red',
|
|
309
|
+
icon: 'trash',
|
|
310
|
+
selectionMode: 'multi',
|
|
311
|
+
hasConfirmMessage: true,
|
|
312
|
+
confirmMessage: 'Are you sure you want to delete these rows?'
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
name: 'Edit',
|
|
316
|
+
function: (selectedRows) => handleEdit(selectedRows[0]),
|
|
317
|
+
tooltip: 'Edit selected row',
|
|
318
|
+
color: 'blue',
|
|
319
|
+
icon: 'edit',
|
|
320
|
+
selectionMode: 'single'
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
name: 'Add New',
|
|
324
|
+
function: () => handleAdd(),
|
|
325
|
+
tooltip: 'Add new record',
|
|
326
|
+
color: 'green',
|
|
327
|
+
icon: 'plus',
|
|
328
|
+
selectionMode: 'always'
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
name: 'Archive Mode',
|
|
332
|
+
function: () => toggleArchiveMode(),
|
|
333
|
+
tooltip: 'Toggle archive view',
|
|
334
|
+
color: 'grey',
|
|
335
|
+
icon: 'archive',
|
|
336
|
+
toggle: true,
|
|
337
|
+
active: isArchiveMode,
|
|
338
|
+
selectionMode: 'always'
|
|
339
|
+
}
|
|
340
|
+
]}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
#### `extraActions`
|
|
344
|
+
- **Type:** `Array<ExtraActionObject>`
|
|
345
|
+
- **Default:** `null`
|
|
346
|
+
- **Description:** Additional custom action buttons displayed on the right side of the toolbar
|
|
347
|
+
- **Extra Action Object Properties:**
|
|
348
|
+
- `function` (function, required): Callback when button is clicked
|
|
349
|
+
- `content` (string|element, required): Button content/label
|
|
350
|
+
- `tooltip` (string): Tooltip text on hover
|
|
351
|
+
- `icon` (string|element): Icon name or React element
|
|
352
|
+
- `style` (object): Custom CSS styles for the button
|
|
353
|
+
- `propsButton` (object): Additional props passed to Semantic UI Button component
|
|
354
|
+
- **Example:**
|
|
355
|
+
```jsx
|
|
356
|
+
extraActions={[
|
|
357
|
+
{
|
|
358
|
+
function: () => openSettings(),
|
|
359
|
+
content: 'Settings',
|
|
360
|
+
tooltip: 'Open settings',
|
|
361
|
+
icon: 'setting',
|
|
362
|
+
style: { backgroundColor: '#f0f0f0' }
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
function: () => downloadReport(),
|
|
366
|
+
content: 'Download',
|
|
367
|
+
tooltip: 'Download report',
|
|
368
|
+
icon: 'download',
|
|
369
|
+
propsButton: { loading: isDownloading }
|
|
370
|
+
}
|
|
371
|
+
]}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### `enableTopToolbar`
|
|
375
|
+
- **Type:** `boolean`
|
|
376
|
+
- **Default:** `true`
|
|
377
|
+
- **Description:** Show/hide the top toolbar containing actions and pagination
|
|
378
|
+
|
|
379
|
+
#### `enableBottomToolbar`
|
|
380
|
+
- **Type:** `boolean`
|
|
381
|
+
- **Default:** `false`
|
|
382
|
+
- **Description:** Show/hide the bottom toolbar
|
|
383
|
+
|
|
384
|
+
#### `hasClearFiltersBtn`
|
|
385
|
+
- **Type:** `boolean`
|
|
386
|
+
- **Default:** `true`
|
|
387
|
+
- **Description:** Show/hide the "Clear Filters" button in toolbar
|
|
388
|
+
|
|
389
|
+
#### `hasClearSelectionBtn`
|
|
390
|
+
- **Type:** `boolean`
|
|
391
|
+
- **Default:** `true`
|
|
392
|
+
- **Description:** Show/hide the "Clear Selection" button in toolbar
|
|
393
|
+
- **Note:** Only visible when `disableSelect={false}` or `disableRows` array has items
|
|
394
|
+
|
|
395
|
+
#### `disableAllActions`
|
|
396
|
+
- **Type:** `boolean`
|
|
397
|
+
- **Default:** `false`
|
|
398
|
+
- **Description:** Hide all action buttons in the top toolbar
|
|
399
|
+
|
|
400
|
+
#### `disableSideActions`
|
|
401
|
+
- **Type:** `boolean`
|
|
402
|
+
- **Default:** `false`
|
|
403
|
+
- **Description:** Hide side action buttons (export, cache, clear filters, help) while keeping main actions visible
|
|
404
|
+
|
|
405
|
+
#### `gridHelper`
|
|
406
|
+
- **Type:** `object | null`
|
|
407
|
+
- **Default:** `null`
|
|
408
|
+
- **Description:** Adds a help button with custom content in a modal dialog
|
|
409
|
+
- **Required Properties (if defined):**
|
|
410
|
+
- `title` (string|element, required): Help dialog title
|
|
411
|
+
- `content` (string|element, required): Help dialog content
|
|
412
|
+
- **Example:**
|
|
413
|
+
```jsx
|
|
414
|
+
gridHelper={{
|
|
415
|
+
title: 'Grid Instructions',
|
|
416
|
+
content: (
|
|
417
|
+
<div>
|
|
418
|
+
<h3>How to use this grid:</h3>
|
|
419
|
+
<ul>
|
|
420
|
+
<li>Use the filters above each column to search data</li>
|
|
421
|
+
<li>Click rows to select them</li>
|
|
422
|
+
<li>Use action buttons to perform operations</li>
|
|
423
|
+
<li>Export data using the Excel or PDF buttons</li>
|
|
424
|
+
</ul>
|
|
425
|
+
</div>
|
|
426
|
+
)
|
|
427
|
+
}}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### Export Options
|
|
433
|
+
|
|
434
|
+
#### `hasExcelExport`
|
|
435
|
+
- **Type:** `boolean`
|
|
436
|
+
- **Default:** `false`
|
|
437
|
+
- **Description:** Enable Excel export button in the toolbar
|
|
438
|
+
|
|
439
|
+
#### `hasPdfExport`
|
|
440
|
+
- **Type:** `boolean`
|
|
441
|
+
- **Default:** `false`
|
|
442
|
+
- **Description:** Enable PDF export button in the toolbar
|
|
443
|
+
|
|
444
|
+
**Export Behavior:**
|
|
445
|
+
- Both export buttons are rendered by the `ExportActions` component
|
|
446
|
+
- Exports respect current filters and column visibility
|
|
447
|
+
- Selected rows can be exported if selection is enabled
|
|
448
|
+
- Export filename is auto-generated or can be customized
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
### Selection & Interaction
|
|
453
|
+
|
|
454
|
+
#### `disableSelect`
|
|
455
|
+
- **Type:** `boolean`
|
|
456
|
+
- **Default:** `false`
|
|
457
|
+
- **Description:** Completely disable row selection checkboxes and click-to-select behavior
|
|
458
|
+
|
|
459
|
+
#### `enableMultiRowSelection`
|
|
460
|
+
- **Type:** `boolean`
|
|
461
|
+
- **Default:** `true`
|
|
462
|
+
- **Description:** Allow selecting multiple rows at once
|
|
463
|
+
- **Behavior:**
|
|
464
|
+
- `true` - Users can select multiple rows using checkboxes or Shift+Click
|
|
465
|
+
- `false` - Only one row can be selected at a time
|
|
466
|
+
|
|
467
|
+
#### `selectAllMode`
|
|
468
|
+
- **Type:** `string`
|
|
469
|
+
- **Default:** `'page'`
|
|
470
|
+
- **Options:** `'page'`, `'all'`
|
|
471
|
+
- **Description:**
|
|
472
|
+
- `'page'` - "Select All" checkbox selects only rows on current page
|
|
473
|
+
- `'all'` - "Select All" checkbox selects all filtered rows across all pages
|
|
474
|
+
|
|
475
|
+
#### `selectedIds`
|
|
476
|
+
- **Type:** `Array`
|
|
477
|
+
- **Default:** `[]`
|
|
478
|
+
- **Description:** Array of row IDs that should be pre-selected when grid loads
|
|
479
|
+
- **Example:**
|
|
480
|
+
```jsx
|
|
481
|
+
selectedIds={[1, 5, 10]} // Pre-select rows with these IDs
|
|
482
|
+
```
|
|
483
|
+
- **Note:** Component syncs automatically when this prop changes
|
|
484
|
+
|
|
485
|
+
#### `disableRows`
|
|
486
|
+
- **Type:** `Array`
|
|
487
|
+
- **Default:** `[]`
|
|
488
|
+
- **Description:** Array of row IDs (based on `rowKey`) that should be disabled and cannot be selected
|
|
489
|
+
- **Example:**
|
|
490
|
+
```jsx
|
|
491
|
+
disableRows={[3, 7, 9]} // Disable selection for these row IDs
|
|
492
|
+
```
|
|
493
|
+
- **Visual:** Disabled rows are shown with gray background (`#e3e3e3`)
|
|
494
|
+
|
|
495
|
+
#### `hasSubRows`
|
|
496
|
+
- **Type:** `boolean`
|
|
497
|
+
- **Default:** `false`
|
|
498
|
+
- **Description:** Enable support for hierarchical/nested rows
|
|
499
|
+
- **Requirements:** Data must include `subRows` property for parent rows
|
|
500
|
+
- **Example Data:**
|
|
501
|
+
```jsx
|
|
502
|
+
const data = [
|
|
503
|
+
{
|
|
504
|
+
id: 1,
|
|
505
|
+
name: 'Parent Row',
|
|
506
|
+
subRows: [
|
|
507
|
+
{ id: '1.1', name: 'Child Row 1' },
|
|
508
|
+
{ id: '1.2', name: 'Child Row 2' }
|
|
509
|
+
]
|
|
510
|
+
}
|
|
511
|
+
];
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
#### `enableExpanding`
|
|
515
|
+
- **Type:** `boolean`
|
|
516
|
+
- **Default:** `false`
|
|
517
|
+
- **Description:** Show expand/collapse icons for rows with subRows
|
|
518
|
+
- **Requires:** `hasSubRows={true}`
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
### Pagination & Display
|
|
523
|
+
|
|
524
|
+
#### `enablePagination`
|
|
525
|
+
- **Type:** `boolean`
|
|
526
|
+
- **Default:** `true`
|
|
527
|
+
- **Description:** Enable/disable pagination controls
|
|
528
|
+
|
|
529
|
+
#### `pagination`
|
|
530
|
+
- **Type:** `string`
|
|
531
|
+
- **Default:** `'both'`
|
|
532
|
+
- **Options:** `'top'`, `'bottom'`, `'both'`
|
|
533
|
+
- **Description:** Position of pagination controls
|
|
534
|
+
- **Note:** When using `'top'`, pagination is integrated into the top toolbar
|
|
535
|
+
|
|
536
|
+
#### `pageSize`
|
|
537
|
+
- **Type:** `number`
|
|
538
|
+
- **Default:** `150`
|
|
539
|
+
- **Description:** Number of rows displayed per page initially
|
|
540
|
+
|
|
541
|
+
#### `itemsPerPage`
|
|
542
|
+
- **Type:** `Array<number>`
|
|
543
|
+
- **Default:** `[50, 100, 150]`
|
|
544
|
+
- **Description:** Options available in the rows-per-page dropdown
|
|
545
|
+
- **Example:**
|
|
546
|
+
```jsx
|
|
547
|
+
itemsPerPage={[10, 25, 50, 100, 200]}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
### Styling & Layout
|
|
553
|
+
|
|
554
|
+
#### `rowHeight`
|
|
555
|
+
- **Type:** `number`
|
|
556
|
+
- **Default:** `75`
|
|
557
|
+
- **Description:** Minimum height of each row in pixels
|
|
558
|
+
|
|
559
|
+
#### `fontSize`
|
|
560
|
+
- **Type:** `number`
|
|
561
|
+
- **Default:** `14`
|
|
562
|
+
- **Description:** Base font size for grid content in pixels
|
|
563
|
+
- **Compact Mode:** When `enableCompactStyleMode={true}`, responsive sizing is used: `clamp(fontSize-3px, 1.1vw, fontSize)`
|
|
564
|
+
|
|
565
|
+
#### `gridHeight`
|
|
566
|
+
- **Type:** `number | string`
|
|
567
|
+
- **Default:** `600`
|
|
568
|
+
- **Description:** Maximum height of the grid container
|
|
569
|
+
- **Examples:**
|
|
570
|
+
```jsx
|
|
571
|
+
gridHeight={600} // 600px fixed height
|
|
572
|
+
gridHeight="80vh" // 80% of viewport height
|
|
573
|
+
gridHeight="calc(100vh - 200px)" // Dynamic height calculation
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
#### `enableCompactStyleMode`
|
|
577
|
+
- **Type:** `boolean`
|
|
578
|
+
- **Default:** `false`
|
|
579
|
+
- **Description:** Enable compact styling with reduced padding and responsive font sizes
|
|
580
|
+
- **Features:**
|
|
581
|
+
- Reduced cell padding (2px vs auto)
|
|
582
|
+
- Responsive font sizing using CSS clamp()
|
|
583
|
+
- Tighter filter input heights (17px vs default)
|
|
584
|
+
- Reduced column header spacing
|
|
585
|
+
- Optimized for displaying dense data
|
|
586
|
+
|
|
587
|
+
#### `getRowStyle`
|
|
588
|
+
- **Type:** `function`
|
|
589
|
+
- **Description:** Custom function to apply conditional styles to rows based on data
|
|
590
|
+
- **Signature:** `({ row }) => object`
|
|
591
|
+
- **Example:**
|
|
592
|
+
```jsx
|
|
593
|
+
getRowStyle={({ row }) => {
|
|
594
|
+
const styles = {};
|
|
595
|
+
|
|
596
|
+
if (row.original.status === 'active') {
|
|
597
|
+
styles.backgroundColor = '#e8f5e9';
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (row.original.priority === 'high') {
|
|
601
|
+
styles.color = 'red';
|
|
602
|
+
styles.fontWeight = 'bold';
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
if (row.original.isExpired) {
|
|
606
|
+
styles.opacity = 0.6;
|
|
607
|
+
styles.textDecoration = 'line-through';
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return styles;
|
|
611
|
+
}}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
#### `enableFixedHeader`
|
|
615
|
+
- **Type:** `boolean`
|
|
616
|
+
- **Default:** `true`
|
|
617
|
+
- **Description:** Pin column headers to top when scrolling vertically
|
|
618
|
+
- **Implementation:** Uses CSS sticky positioning with class `grid-sticky-header`
|
|
619
|
+
|
|
620
|
+
#### `enableFixedActions`
|
|
621
|
+
- **Type:** `boolean`
|
|
622
|
+
- **Default:** `false`
|
|
623
|
+
- **Description:** Pin action toolbar to top when scrolling
|
|
624
|
+
- **Requires:** `enableFixedHeader={true}`
|
|
625
|
+
- **Implementation:** Uses CSS sticky positioning with class `grid-sticky-actions`
|
|
626
|
+
|
|
627
|
+
---
|
|
628
|
+
|
|
629
|
+
### Advanced Features
|
|
630
|
+
|
|
631
|
+
#### `enableGlobalFilter`
|
|
632
|
+
- **Type:** `boolean`
|
|
633
|
+
- **Default:** `false`
|
|
634
|
+
- **Description:** Show global search input that filters across all columns
|
|
635
|
+
|
|
636
|
+
#### `globalFilterFn`
|
|
637
|
+
- **Type:** `string`
|
|
638
|
+
- **Default:** `'contains'`
|
|
639
|
+
- **Options:** `'contains'`, `'fuzzy'`, `'between'`, `'equals'`, `'greaterThan'`, `'lessThan'`, `'notEquals'`, `'lessThanOrEqualTo'`, `'greaterThanOrEqualTo'`, `'empty'`, `'notEmpty'`, `'startsWith'`, `'endsWith'`, `'betweenInclusive'`
|
|
640
|
+
- **Description:** Filter function used for global search
|
|
641
|
+
|
|
642
|
+
#### `enableColumnFilterModes`
|
|
643
|
+
- **Type:** `boolean`
|
|
644
|
+
- **Default:** `true`
|
|
645
|
+
- **Description:** Allow users to change filter type per column (contains, equals, regex, etc.)
|
|
646
|
+
- **Available Modes:** Rendered through `ColumnFilter` component
|
|
647
|
+
|
|
648
|
+
#### `enableVirtualization`
|
|
649
|
+
- **Type:** `boolean`
|
|
650
|
+
- **Default:** `false`
|
|
651
|
+
- **Description:** Enable row and column virtualization for large datasets
|
|
652
|
+
- **Recommended:** For grids with 1000+ rows
|
|
653
|
+
- **Configuration:**
|
|
654
|
+
- Row virtualizer: `overscan: 5`
|
|
655
|
+
- Column virtualizer: `overscan: columns.length`
|
|
656
|
+
- Scroll-to-top on sort change
|
|
657
|
+
|
|
658
|
+
#### `enableFullScreenToggle`
|
|
659
|
+
- **Type:** `boolean`
|
|
660
|
+
- **Default:** `false`
|
|
661
|
+
- **Description:** Show fullscreen toggle button in toolbar
|
|
662
|
+
|
|
663
|
+
#### `enableDensityToggle`
|
|
664
|
+
- **Type:** `boolean`
|
|
665
|
+
- **Default:** `false`
|
|
666
|
+
- **Description:** Show density toggle button (compact/comfortable/spacious)
|
|
667
|
+
|
|
668
|
+
---
|
|
669
|
+
|
|
670
|
+
### Cache & Updates
|
|
671
|
+
|
|
672
|
+
#### `updateCache`
|
|
673
|
+
- **Type:** `function`
|
|
674
|
+
- **Default:** `undefined`
|
|
675
|
+
- **Description:** Callback function triggered when cache update button is clicked
|
|
676
|
+
- **Signature:** `() => void`
|
|
677
|
+
- **Example:**
|
|
678
|
+
```jsx
|
|
679
|
+
updateCache={() => {
|
|
680
|
+
fetchLatestData();
|
|
681
|
+
}}
|
|
682
|
+
```
|
|
683
|
+
- **Note:** Cache button only appears when this prop is provided
|
|
684
|
+
|
|
685
|
+
#### `cacheUpdateText`
|
|
686
|
+
- **Type:** `string`
|
|
687
|
+
- **Default:** `undefined`
|
|
688
|
+
- **Description:** Tooltip text displayed on hover over the cache update button
|
|
689
|
+
- **Example:** `"Refresh data from server"`
|
|
690
|
+
|
|
691
|
+
#### `cacheUpdating`
|
|
692
|
+
- **Type:** `boolean`
|
|
693
|
+
- **Default:** `false`
|
|
694
|
+
- **Description:** Shows loading state on cache update button
|
|
695
|
+
- **Visual:** Changes button icon to loading spinner
|
|
696
|
+
- **Disables:** Button is disabled while `true`
|
|
697
|
+
|
|
698
|
+
---
|
|
699
|
+
|
|
700
|
+
### Callbacks
|
|
701
|
+
|
|
702
|
+
#### `onVisibleRowsChange`
|
|
703
|
+
- **Type:** `function`
|
|
704
|
+
- **Description:** Called whenever the visible rows change (filtering, sorting, pagination)
|
|
705
|
+
- **Signature:** `(visibleRows: Array<Object>) => void`
|
|
706
|
+
- **Example:**
|
|
707
|
+
```jsx
|
|
708
|
+
onVisibleRowsChange={(rows) => {
|
|
709
|
+
console.log('Currently visible:', rows.length);
|
|
710
|
+
updateDashboardStats(rows);
|
|
711
|
+
}}
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
---
|
|
715
|
+
|
|
716
|
+
## Column Types
|
|
717
|
+
|
|
718
|
+
The DataGrid supports various pre-built cell types via the `type` property in column definitions. These formatters are automatically applied without requiring custom cell components.
|
|
719
|
+
|
|
720
|
+
### Text Types
|
|
721
|
+
- **`text`** - Plain text display
|
|
722
|
+
- **`textTitle`** - Bold text (font-weight: bold)
|
|
723
|
+
- **`textDescription`** - Gray text (#666666)
|
|
724
|
+
- **`textSmall`** - Small font size text
|
|
725
|
+
|
|
726
|
+
### Date Types
|
|
727
|
+
- **`date`** - Date only (no time) - Format: locale-specific date
|
|
728
|
+
- **`datetime`** - Date with time - Format: locale-specific datetime
|
|
729
|
+
|
|
730
|
+
### Number Types
|
|
731
|
+
- **`number`** - Raw number display
|
|
732
|
+
- **`integer`** - Rounded integer (Math.round)
|
|
733
|
+
- **`currency`** - EUR currency format (€1,234.56)
|
|
734
|
+
- **`percentage`** - Percentage format (12.34%)
|
|
735
|
+
|
|
736
|
+
### Link Types
|
|
737
|
+
- **`email`** - Clickable mailto link (`<a href="mailto:...">`)
|
|
738
|
+
- **`phone`** - Clickable tel link (`<a href="tel:...">`)
|
|
739
|
+
- **`link`** - External link that opens in new tab (`target="_blank"`)
|
|
740
|
+
|
|
741
|
+
### Complex Types
|
|
742
|
+
- **`array`** - Comma-separated array values
|
|
743
|
+
- **`json`** - Formatted JSON display with indentation
|
|
744
|
+
- **`countryFlag`** - Country flag image (requires ISO2 country code)
|
|
745
|
+
- **`persons`** - List of persons with "et al." for 3+ people
|
|
746
|
+
|
|
747
|
+
### Example with Types
|
|
748
|
+
|
|
749
|
+
```jsx
|
|
750
|
+
const columns = [
|
|
751
|
+
{ accessorKey: 'name', header: 'Name', type: 'textTitle' },
|
|
752
|
+
{ accessorKey: 'description', header: 'Description', type: 'textDescription' },
|
|
753
|
+
{ accessorKey: 'email', header: 'Email', type: 'email' },
|
|
754
|
+
{ accessorKey: 'phone', header: 'Phone', type: 'phone' },
|
|
755
|
+
{ accessorKey: 'website', header: 'Website', type: 'link' },
|
|
756
|
+
{ accessorKey: 'salary', header: 'Salary', type: 'currency' },
|
|
757
|
+
{ accessorKey: 'completion', header: 'Progress', type: 'percentage' },
|
|
758
|
+
{ accessorKey: 'createdAt', header: 'Created', type: 'date', isDateColumn: true },
|
|
759
|
+
{ accessorKey: 'lastUpdated', header: 'Last Updated', type: 'datetime', isDateColumn: true },
|
|
760
|
+
{ accessorKey: 'country', header: 'Country', type: 'countryFlag' },
|
|
761
|
+
{ accessorKey: 'tags', header: 'Tags', type: 'array' },
|
|
762
|
+
{ accessorKey: 'metadata', header: 'Metadata', type: 'json' },
|
|
763
|
+
{ accessorKey: 'authors', header: 'Authors', type: 'persons' },
|
|
764
|
+
];
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
### Custom Cell Renderers with Type Support
|
|
768
|
+
|
|
769
|
+
You have multiple options for cell rendering, each serving different use cases:
|
|
770
|
+
|
|
771
|
+
#### Option 1: Using Type Alone (Simplest)
|
|
772
|
+
Best for: Standard formatting without custom logic
|
|
773
|
+
```jsx
|
|
774
|
+
const columns = [
|
|
775
|
+
{
|
|
776
|
+
accessorKey: 'price',
|
|
777
|
+
header: 'Price',
|
|
778
|
+
type: 'currency' // Automatically formatted as €1,234.56
|
|
779
|
+
}
|
|
780
|
+
];
|
|
781
|
+
// No custom Cell needed - formatter is applied automatically
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
#### Option 2: Type + cellClass
|
|
785
|
+
Best for: Adding CSS styling to formatted content
|
|
786
|
+
```jsx
|
|
787
|
+
const columns = [
|
|
788
|
+
{
|
|
789
|
+
accessorKey: 'status',
|
|
790
|
+
header: 'Status',
|
|
791
|
+
type: 'text',
|
|
792
|
+
cellClass: 'status-badge' // Formatted text wrapped in <div class="status-badge">
|
|
793
|
+
}
|
|
794
|
+
];
|
|
795
|
+
```
|
|
796
|
+
|
|
797
|
+
#### Option 3: Type + Custom Cell (Advanced)
|
|
798
|
+
Best for: Custom logic or styling while preserving type formatting
|
|
799
|
+
```jsx
|
|
800
|
+
// Custom cell that uses the type formatter and adds custom styling
|
|
801
|
+
const CustomStatusCell = ({ typeValue, cell, row }) => {
|
|
802
|
+
const rawValue = cell.getValue();
|
|
803
|
+
const formattedValue = typeValue; // Pre-formatted by type formatter
|
|
804
|
+
|
|
805
|
+
return (
|
|
806
|
+
<div style={{
|
|
807
|
+
color: rawValue === 'active' ? 'green' : 'red',
|
|
808
|
+
fontWeight: 'bold',
|
|
809
|
+
padding: '4px 8px',
|
|
810
|
+
borderRadius: '4px',
|
|
811
|
+
backgroundColor: rawValue === 'active' ? '#e8f5e9' : '#ffebee'
|
|
812
|
+
}}>
|
|
813
|
+
{formattedValue || rawValue} {/* Use formatted value or fallback */}
|
|
814
|
+
</div>
|
|
815
|
+
);
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
const columns = [
|
|
819
|
+
{
|
|
820
|
+
accessorKey: 'status',
|
|
821
|
+
header: 'Status',
|
|
822
|
+
type: 'text', // Formatter is applied first
|
|
823
|
+
Cell: CustomStatusCell, // Custom component receives typeValue prop
|
|
824
|
+
}
|
|
825
|
+
];
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
#### Option 4: Custom Cell Only (No Type)
|
|
829
|
+
Best for: Complete custom rendering without any formatter
|
|
830
|
+
```jsx
|
|
831
|
+
const CustomCell = ({ cell, row }) => {
|
|
832
|
+
const value = cell.getValue();
|
|
833
|
+
|
|
834
|
+
return (
|
|
835
|
+
<div className="custom-cell">
|
|
836
|
+
<strong>{value}</strong>
|
|
837
|
+
<span className="badge">{row.original.count}</span>
|
|
838
|
+
</div>
|
|
839
|
+
);
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
const columns = [
|
|
843
|
+
{
|
|
844
|
+
accessorKey: 'name',
|
|
845
|
+
header: 'Name',
|
|
846
|
+
Cell: CustomCell // No type - full control over rendering
|
|
847
|
+
}
|
|
848
|
+
];
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
#### Custom Cell Props Reference
|
|
852
|
+
|
|
853
|
+
When using a custom `Cell` component, you receive these props:
|
|
854
|
+
|
|
855
|
+
```typescript
|
|
856
|
+
{
|
|
857
|
+
cell: Object, // MRT cell instance
|
|
858
|
+
row: Object, // MRT row instance
|
|
859
|
+
table: Object, // MRT table instance
|
|
860
|
+
typeValue: any, // Formatted value from type formatter (if type is defined)
|
|
861
|
+
// Standard MRT props...
|
|
862
|
+
}
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
**Important:** Access `row.original` to get the original data object.
|
|
866
|
+
|
|
867
|
+
---
|
|
868
|
+
|
|
869
|
+
**How Cell Rendering Works:**
|
|
870
|
+
|
|
871
|
+
1. **accessorFn/accessorKey evaluated:** Value is extracted from row data
|
|
872
|
+
2. **Type formatter applied:** If `type` is specified, `DEFAULT_CELL_TYPES[type]` processes the value
|
|
873
|
+
3. **Content assigned:** Formatted value becomes the base `content`
|
|
874
|
+
4. **Custom Cell receives props:** If `Cell` is defined, it receives:
|
|
875
|
+
- `typeValue`: The pre-formatted value
|
|
876
|
+
- All standard MRT cell props
|
|
877
|
+
5. **CSS wrapper:** If `cellClass` is defined, final content is wrapped in `<div className={cellClass}>`
|
|
878
|
+
|
|
879
|
+
**Rendering Priority:**
|
|
880
|
+
```
|
|
881
|
+
Raw Data → accessorFn → Type Formatter → typeValue → Custom Cell → cellClass Wrapper → Final Output
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
**When to use each approach:**
|
|
885
|
+
- Use **type only** for standard formatting (95% of cases)
|
|
886
|
+
- Use **type + cellClass** for simple styling needs
|
|
887
|
+
- Use **type + Cell** when you need formatting AND custom logic
|
|
888
|
+
- Use **Cell only** for completely custom rendering
|
|
889
|
+
|
|
890
|
+
---
|
|
891
|
+
|
|
892
|
+
## Examples
|
|
893
|
+
|
|
894
|
+
### Example 1: Basic Grid with Selection
|
|
895
|
+
|
|
896
|
+
```jsx
|
|
897
|
+
import React, { useState } from 'react';
|
|
898
|
+
import DataGrid from '@insticc/react-datagrid-2';
|
|
899
|
+
|
|
900
|
+
function UserGrid() {
|
|
901
|
+
const [selected, setSelected] = useState([]);
|
|
902
|
+
|
|
903
|
+
const columns = [
|
|
904
|
+
{ accessorKey: 'id', header: 'ID', type: 'integer' },
|
|
905
|
+
{ accessorKey: 'name', header: 'Name', type: 'textTitle' },
|
|
906
|
+
{ accessorKey: 'email', header: 'Email', type: 'email' },
|
|
907
|
+
{ accessorKey: 'role', header: 'Role', type: 'text' },
|
|
908
|
+
{ accessorKey: 'createdAt', header: 'Joined', type: 'date', isDateColumn: true },
|
|
909
|
+
];
|
|
910
|
+
|
|
911
|
+
const users = [
|
|
912
|
+
{ id: 1, name: 'John Doe', email: 'john@company.com', role: 'Admin', createdAt: '2024-01-15' },
|
|
913
|
+
{ id: 2, name: 'Jane Smith', email: 'jane@company.com', role: 'User', createdAt: '2024-02-20' },
|
|
914
|
+
{ id: 3, name: 'Bob Johnson', email: 'bob@company.com', role: 'Manager', createdAt: '2024-03-10' },
|
|
915
|
+
];
|
|
916
|
+
|
|
917
|
+
return (
|
|
918
|
+
<DataGrid
|
|
919
|
+
columns={columns}
|
|
920
|
+
createRows={users}
|
|
921
|
+
rowKey="id"
|
|
922
|
+
selectData={setSelected}
|
|
923
|
+
pageSize={50}
|
|
924
|
+
itemsPerPage={[25, 50, 100]}
|
|
925
|
+
gridHeight={500}
|
|
926
|
+
/>
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
```
|
|
930
|
+
|
|
931
|
+
### Example 2: Using accessorFn for Complex Data
|
|
932
|
+
|
|
933
|
+
```jsx
|
|
934
|
+
function ConferenceGrid() {
|
|
935
|
+
const [selected, setSelected] = useState([]);
|
|
936
|
+
|
|
937
|
+
const columns = [
|
|
938
|
+
{
|
|
939
|
+
accessorKey: 'acronym',
|
|
940
|
+
accessorFn: (row) => row.acronym ?? '', // Handle null/undefined
|
|
941
|
+
header: 'Acronym',
|
|
942
|
+
type: 'textTitle'
|
|
943
|
+
},
|
|
944
|
+
{
|
|
945
|
+
accessorKey: 'fullName',
|
|
946
|
+
accessorFn: (row) => `${row.shortName || ''} - ${row.year || ''}`, // Combine fields
|
|
947
|
+
header: 'Conference Name',
|
|
948
|
+
type: 'text'
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
accessorKey: 'papers',
|
|
952
|
+
accessorFn: (row) => row.numberPapers?.value ?? 0, // Nested object with fallback
|
|
953
|
+
header: 'Papers',
|
|
954
|
+
type: 'integer'
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
accessorKey: 'averageRating',
|
|
958
|
+
accessorFn: (row) => row.ratings?.average ?? 0, // Nested with default
|
|
959
|
+
header: 'Avg Rating',
|
|
960
|
+
type: 'number'
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
accessorKey: 'status',
|
|
964
|
+
accessorFn: (row) => row.isActive ? 'Active' : 'Inactive', // Conditional
|
|
965
|
+
header: 'Status',
|
|
966
|
+
type: 'text'
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
accessorKey: 'organizers',
|
|
970
|
+
accessorFn: (row) => row.organizers?.map(o => o.name).join(', ') ?? 'N/A', // Array processing
|
|
971
|
+
header: 'Organizers',
|
|
972
|
+
type: 'text'
|
|
973
|
+
}
|
|
974
|
+
];
|
|
975
|
+
|
|
976
|
+
const conferences = [
|
|
977
|
+
{
|
|
978
|
+
id: 1,
|
|
979
|
+
acronym: 'ICEIS',
|
|
980
|
+
shortName: 'International Conference on Enterprise Information Systems',
|
|
981
|
+
year: 2025,
|
|
982
|
+
numberPapers: { value: 150, trend: 'up' },
|
|
983
|
+
ratings: { average: 4.5, count: 200 },
|
|
984
|
+
isActive: true,
|
|
985
|
+
organizers: [{ name: 'John Doe' }, { name: 'Jane Smith' }]
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
id: 2,
|
|
989
|
+
acronym: null, // Will be handled by accessorFn
|
|
990
|
+
shortName: 'Conference on AI',
|
|
991
|
+
year: 2024,
|
|
992
|
+
numberPapers: null, // Will default to 0
|
|
993
|
+
ratings: { average: 3.8, count: 50 },
|
|
994
|
+
isActive: false,
|
|
995
|
+
organizers: []
|
|
996
|
+
}
|
|
997
|
+
];
|
|
998
|
+
|
|
999
|
+
return (
|
|
1000
|
+
<DataGrid
|
|
1001
|
+
columns={columns}
|
|
1002
|
+
createRows={conferences}
|
|
1003
|
+
rowKey="id"
|
|
1004
|
+
selectData={setSelected}
|
|
1005
|
+
gridHeight={600}
|
|
1006
|
+
/>
|
|
1007
|
+
);
|
|
1008
|
+
}
|
|
1009
|
+
```
|
|
1010
|
+
|
|
1011
|
+
### Example 3: Grid with Actions and Exports
|
|
1012
|
+
|
|
1013
|
+
```jsx
|
|
1014
|
+
function ProductGrid() {
|
|
1015
|
+
const [selectedProducts, setSelectedProducts] = useState([]);
|
|
1016
|
+
const [products, setProducts] = useState(initialProducts);
|
|
1017
|
+
|
|
1018
|
+
const handleDelete = (rows) => {
|
|
1019
|
+
const ids = rows.map(r => r.productId);
|
|
1020
|
+
if (window.confirm(`Delete ${ids.length} product(s)?`)) {
|
|
1021
|
+
setProducts(prev => prev.filter(p => !ids.includes(p.productId)));
|
|
1022
|
+
}
|
|
1023
|
+
};
|
|
1024
|
+
|
|
1025
|
+
const handleEdit = (rows) => {
|
|
1026
|
+
if (rows.length === 1) {
|
|
1027
|
+
openEditModal(rows[0]);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
|
|
1031
|
+
const handleAddNew = () => {
|
|
1032
|
+
openCreateModal();
|
|
1033
|
+
};
|
|
1034
|
+
|
|
1035
|
+
const actions = [
|
|
1036
|
+
{
|
|
1037
|
+
name: 'Delete',
|
|
1038
|
+
function: handleDelete,
|
|
1039
|
+
tooltip: 'Delete selected products',
|
|
1040
|
+
color: 'red',
|
|
1041
|
+
icon: 'trash',
|
|
1042
|
+
selectionMode: 'multi',
|
|
1043
|
+
hasConfirmMessage: true,
|
|
1044
|
+
confirmMessage: 'Are you sure you want to delete the selected products?'
|
|
1045
|
+
},
|
|
1046
|
+
{
|
|
1047
|
+
name: 'Edit',
|
|
1048
|
+
function: handleEdit,
|
|
1049
|
+
tooltip: 'Edit product',
|
|
1050
|
+
color: 'blue',
|
|
1051
|
+
icon: 'edit',
|
|
1052
|
+
selectionMode: 'single'
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
name: 'Add Product',
|
|
1056
|
+
function: handleAddNew,
|
|
1057
|
+
tooltip: 'Add new product',
|
|
1058
|
+
color: 'green',
|
|
1059
|
+
icon: 'plus',
|
|
1060
|
+
selectionMode: 'always'
|
|
1061
|
+
}
|
|
1062
|
+
];
|
|
1063
|
+
|
|
1064
|
+
const columns = [
|
|
1065
|
+
{ accessorKey: 'productId', header: 'ID', type: 'integer' },
|
|
1066
|
+
{ accessorKey: 'name', header: 'Product Name', type: 'textTitle' },
|
|
1067
|
+
{
|
|
1068
|
+
accessorKey: 'price',
|
|
1069
|
+
accessorFn: (row) => row.price ?? 0, // Ensure numeric value
|
|
1070
|
+
header: 'Price',
|
|
1071
|
+
type: 'currency'
|
|
1072
|
+
},
|
|
1073
|
+
{ accessorKey: 'stock', header: 'Stock', type: 'integer' },
|
|
1074
|
+
{ accessorKey: 'category', header: 'Category', type: 'text' },
|
|
1075
|
+
];
|
|
1076
|
+
|
|
1077
|
+
return (
|
|
1078
|
+
<DataGrid
|
|
1079
|
+
columns={columns}
|
|
1080
|
+
createRows={products}
|
|
1081
|
+
rowKey="productId"
|
|
1082
|
+
selectData={setSelectedProducts}
|
|
1083
|
+
actions={actions}
|
|
1084
|
+
hasExcelExport={true}
|
|
1085
|
+
hasPdfExport={true}
|
|
1086
|
+
gridHeight={600}
|
|
1087
|
+
/>
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
```
|
|
1091
|
+
|
|
1092
|
+
### Example 4: Hierarchical Data with SubRows
|
|
1093
|
+
|
|
1094
|
+
```jsx
|
|
1095
|
+
function ProjectGrid() {
|
|
1096
|
+
const [selectedItems, setSelectedItems] = useState([]);
|
|
1097
|
+
|
|
1098
|
+
const columns = [
|
|
1099
|
+
{ accessorKey: 'name', header: 'Name', type: 'textTitle' },
|
|
1100
|
+
{ accessorKey: 'status', header: 'Status', type: 'text' },
|
|
1101
|
+
{ accessorKey: 'assignee', header: 'Assignee', type: 'text' },
|
|
1102
|
+
{ accessorKey: 'dueDate', header: 'Due Date', type: 'date', isDateColumn: true },
|
|
1103
|
+
];
|
|
1104
|
+
|
|
1105
|
+
const data = [
|
|
1106
|
+
{
|
|
1107
|
+
id: 1,
|
|
1108
|
+
name: 'Project Alpha',
|
|
1109
|
+
status: 'Active',
|
|
1110
|
+
assignee: 'John Doe',
|
|
1111
|
+
dueDate: '2025-06-30',
|
|
1112
|
+
subRows: [
|
|
1113
|
+
{ id: '1.1', name: 'Task 1: Design', status: 'Complete', assignee: 'Jane', dueDate: '2025-02-15' },
|
|
1114
|
+
{ id: '1.2', name: 'Task 2: Development', status: 'In Progress', assignee: 'Bob', dueDate: '2025-04-30' },
|
|
1115
|
+
{ id: '1.3', name: 'Task 3: Testing', status: 'Not Started', assignee: 'Alice', dueDate: '2025-06-15' }
|
|
1116
|
+
]
|
|
1117
|
+
},
|
|
1118
|
+
{
|
|
1119
|
+
id: 2,
|
|
1120
|
+
name: 'Project Beta',
|
|
1121
|
+
status: 'Planning',
|
|
1122
|
+
assignee: 'Jane Smith',
|
|
1123
|
+
dueDate: '2025-12-31',
|
|
1124
|
+
subRows: [
|
|
1125
|
+
{ id: '2.1', name: 'Task 1: Requirements', status: 'In Progress', assignee: 'John', dueDate: '2025-03-01' }
|
|
1126
|
+
]
|
|
1127
|
+
}
|
|
1128
|
+
];
|
|
1129
|
+
|
|
1130
|
+
return (
|
|
1131
|
+
<DataGrid
|
|
1132
|
+
columns={columns}
|
|
1133
|
+
createRows={data}
|
|
1134
|
+
rowKey="id"
|
|
1135
|
+
selectData={setSelectedItems}
|
|
1136
|
+
hasSubRows={true}
|
|
1137
|
+
enableExpanding={true}
|
|
1138
|
+
gridHeight={500}
|
|
1139
|
+
/>
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
```
|
|
1143
|
+
|
|
1144
|
+
### Example 5: Custom Styling and Virtualization
|
|
1145
|
+
|
|
1146
|
+
```jsx
|
|
1147
|
+
function LargeDataGrid() {
|
|
1148
|
+
const [selectedRows, setSelectedRows] = useState([]);
|
|
1149
|
+
|
|
1150
|
+
// Custom cell with type support
|
|
1151
|
+
const StatusCell = ({ typeValue, cell, row }) => {
|
|
1152
|
+
const value = cell.getValue();
|
|
1153
|
+
const getColor = (status) => {
|
|
1154
|
+
switch (status) {
|
|
1155
|
+
case 'active': return 'green';
|
|
1156
|
+
case 'pending': return 'orange';
|
|
1157
|
+
case 'error': return 'red';
|
|
1158
|
+
default: return 'grey';
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
return (
|
|
1163
|
+
<span style={{
|
|
1164
|
+
color: getColor(value),
|
|
1165
|
+
fontWeight: 'bold',
|
|
1166
|
+
padding: '2px 8px',
|
|
1167
|
+
borderRadius: '4px',
|
|
1168
|
+
backgroundColor: `${getColor(value)}22`
|
|
1169
|
+
}}>
|
|
1170
|
+
{typeValue || value}
|
|
1171
|
+
</span>
|
|
1172
|
+
);
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
const PriorityCell = ({ cell, row }) => {
|
|
1176
|
+
const priority = cell.getValue();
|
|
1177
|
+
const icons = {
|
|
1178
|
+
high: '🔴',
|
|
1179
|
+
medium: '🟡',
|
|
1180
|
+
low: '🟢'
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
return (
|
|
1184
|
+
<span>
|
|
1185
|
+
{icons[priority]} {priority.toUpperCase()}
|
|
1186
|
+
</span>
|
|
1187
|
+
);
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
const getRowStyle = ({ row }) => {
|
|
1191
|
+
const styles = {};
|
|
1192
|
+
|
|
1193
|
+
if (row.original.status === 'error') {
|
|
1194
|
+
styles.backgroundColor = '#ffebee';
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
if (row.original.priority === 'high') {
|
|
1198
|
+
styles.borderLeft = '3px solid red';
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
if (row.original.isArchived) {
|
|
1202
|
+
styles.opacity = 0.5;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
return styles;
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
const columns = [
|
|
1209
|
+
{ accessorKey: 'id', header: 'ID', type: 'integer' },
|
|
1210
|
+
{
|
|
1211
|
+
accessorKey: 'status',
|
|
1212
|
+
header: 'Status',
|
|
1213
|
+
type: 'text',
|
|
1214
|
+
Cell: StatusCell
|
|
1215
|
+
},
|
|
1216
|
+
{
|
|
1217
|
+
accessorKey: 'priority',
|
|
1218
|
+
header: 'Priority',
|
|
1219
|
+
Cell: PriorityCell
|
|
1220
|
+
},
|
|
1221
|
+
{ accessorKey: 'name', header: 'Name', type: 'text' },
|
|
1222
|
+
{
|
|
1223
|
+
accessorKey: 'value',
|
|
1224
|
+
accessorFn: (row) => row.value ?? 0, // Ensure numeric value for currency
|
|
1225
|
+
header: 'Value',
|
|
1226
|
+
type: 'currency'
|
|
1227
|
+
},
|
|
1228
|
+
{
|
|
1229
|
+
accessorKey: 'progress',
|
|
1230
|
+
accessorFn: (row) => row.progress ?? 0, // Ensure numeric value for percentage
|
|
1231
|
+
header: 'Progress',
|
|
1232
|
+
type: 'percentage'
|
|
1233
|
+
},
|
|
1234
|
+
{ accessorKey: 'updatedAt', header: 'Updated', type: 'datetime', isDateColumn: true },
|
|
1235
|
+
];
|
|
1236
|
+
|
|
1237
|
+
// Generate large dataset
|
|
1238
|
+
const largeDataset = Array.from({ length: 5000 }, (_, i) => ({
|
|
1239
|
+
id: i + 1,
|
|
1240
|
+
status: ['active', 'pending', 'error'][i % 3],
|
|
1241
|
+
priority: ['high', 'medium', 'low'][i % 3],
|
|
1242
|
+
name: `Item ${i + 1}`,
|
|
1243
|
+
value: Math.random() * 10000,
|
|
1244
|
+
progress: Math.random(),
|
|
1245
|
+
updatedAt: new Date(Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000).toISOString(),
|
|
1246
|
+
isArchived: i % 10 === 0
|
|
1247
|
+
}));
|
|
1248
|
+
|
|
1249
|
+
return (
|
|
1250
|
+
<DataGrid
|
|
1251
|
+
columns={columns}
|
|
1252
|
+
createRows={largeDataset}
|
|
1253
|
+
rowKey="id"
|
|
1254
|
+
selectData={setSelectedRows}
|
|
1255
|
+
enableVirtualization={true}
|
|
1256
|
+
enableCompactStyleMode={true}
|
|
1257
|
+
rowHeight={40}
|
|
1258
|
+
fontSize={12}
|
|
1259
|
+
gridHeight="calc(100vh - 200px)"
|
|
1260
|
+
getRowStyle={getRowStyle}
|
|
1261
|
+
pageSize={100}
|
|
1262
|
+
itemsPerPage={[50, 100, 200, 500]}
|
|
1263
|
+
/>
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
```
|
|
1267
|
+
|
|
1268
|
+
### Example 6: Advanced Features with Cache Management
|
|
1269
|
+
|
|
1270
|
+
```jsx
|
|
1271
|
+
function AdvancedGrid() {
|
|
1272
|
+
const [data, setData] = useState([]);
|
|
1273
|
+
const [cacheLoading, setCacheLoading] = useState(false);
|
|
1274
|
+
const [selectedRows, setSelectedRows] = useState([]);
|
|
1275
|
+
const [visibleRowCount, setVisibleRowCount] = useState(0);
|
|
1276
|
+
|
|
1277
|
+
const refreshData = async () => {
|
|
1278
|
+
setCacheLoading(true);
|
|
1279
|
+
try {
|
|
1280
|
+
const newData = await fetchLatestData();
|
|
1281
|
+
setData(newData);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
console.error('Failed to refresh data:', error);
|
|
1284
|
+
} finally {
|
|
1285
|
+
setCacheLoading(false);
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
|
|
1289
|
+
const handleVisibleRowsChange = (rows) => {
|
|
1290
|
+
setVisibleRowCount(rows.length);
|
|
1291
|
+
console.log('Visible rows:', rows);
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
const exportCustom = () => {
|
|
1295
|
+
console.log('Custom export logic');
|
|
1296
|
+
};
|
|
1297
|
+
|
|
1298
|
+
const actions = [
|
|
1299
|
+
{
|
|
1300
|
+
name: 'Process',
|
|
1301
|
+
function: (rows) => processSelectedRows(rows),
|
|
1302
|
+
tooltip: 'Process selected items',
|
|
1303
|
+
color: 'blue',
|
|
1304
|
+
icon: 'cog',
|
|
1305
|
+
selectionMode: 'multi'
|
|
1306
|
+
}
|
|
1307
|
+
];
|
|
1308
|
+
|
|
1309
|
+
const extraActions = [
|
|
1310
|
+
{
|
|
1311
|
+
function: exportCustom,
|
|
1312
|
+
content: 'Custom Export',
|
|
1313
|
+
tooltip: 'Export with custom format',
|
|
1314
|
+
icon: 'file alternate outline'
|
|
1315
|
+
}
|
|
1316
|
+
];
|
|
1317
|
+
|
|
1318
|
+
const columns = [
|
|
1319
|
+
{ accessorKey: 'id', header: 'ID', type: 'integer' },
|
|
1320
|
+
{ accessorKey: 'name', header: 'Name', type: 'textTitle' },
|
|
1321
|
+
{ accessorKey: 'status', header: 'Status', type: 'text' },
|
|
1322
|
+
{
|
|
1323
|
+
accessorKey: 'amount',
|
|
1324
|
+
accessorFn: (row) => row.amount ?? 0, // Ensure numeric value
|
|
1325
|
+
header: 'Amount',
|
|
1326
|
+
type: 'currency'
|
|
1327
|
+
},
|
|
1328
|
+
{ accessorKey: 'createdAt', header: 'Created', type: 'datetime', isDateColumn: true },
|
|
1329
|
+
];
|
|
1330
|
+
|
|
1331
|
+
return (
|
|
1332
|
+
<DataGrid
|
|
1333
|
+
columns={columns}
|
|
1334
|
+
createRows={data}
|
|
1335
|
+
rowKey="id"
|
|
1336
|
+
selectData={setSelectedRows}
|
|
1337
|
+
|
|
1338
|
+
// Actions
|
|
1339
|
+
actions={actions}
|
|
1340
|
+
extraActions={extraActions}
|
|
1341
|
+
|
|
1342
|
+
// Advanced features
|
|
1343
|
+
enableGlobalFilter={true}
|
|
1344
|
+
globalFilterFn="fuzzy"
|
|
1345
|
+
enableColumnFilterModes={true}
|
|
1346
|
+
enableFixedHeader={true}
|
|
1347
|
+
enableFixedActions={true}
|
|
1348
|
+
|
|
1349
|
+
// Cache management
|
|
1350
|
+
updateCache={refreshData}
|
|
1351
|
+
cacheUpdateText="Refresh data from server"
|
|
1352
|
+
cacheUpdating={cacheLoading}
|
|
1353
|
+
|
|
1354
|
+
// Callbacks
|
|
1355
|
+
onVisibleRowsChange={handleVisibleRowsChange}
|
|
1356
|
+
|
|
1357
|
+
// Exports
|
|
1358
|
+
hasExcelExport={true}
|
|
1359
|
+
hasPdfExport={true}
|
|
1360
|
+
|
|
1361
|
+
// Help
|
|
1362
|
+
gridHelper={{
|
|
1363
|
+
title: 'Data Grid Help',
|
|
1364
|
+
content: (
|
|
1365
|
+
<div>
|
|
1366
|
+
<h3>Quick Guide</h3>
|
|
1367
|
+
<ul>
|
|
1368
|
+
<li><strong>Selection:</strong> Click rows to select, use checkboxes for multi-select</li>
|
|
1369
|
+
<li><strong>Filtering:</strong> Use column filters to search specific fields</li>
|
|
1370
|
+
<li><strong>Global Search:</strong> Search across all columns at once</li>
|
|
1371
|
+
<li><strong>Sorting:</strong> Click column headers to sort</li>
|
|
1372
|
+
<li><strong>Export:</strong> Use Excel or PDF buttons to export data</li>
|
|
1373
|
+
<li><strong>Refresh:</strong> Click cache button to reload latest data</li>
|
|
1374
|
+
</ul>
|
|
1375
|
+
<p><strong>Currently showing:</strong> {visibleRowCount} rows</p>
|
|
1376
|
+
</div>
|
|
1377
|
+
)
|
|
1378
|
+
}}
|
|
1379
|
+
|
|
1380
|
+
// Display
|
|
1381
|
+
gridHeight={700}
|
|
1382
|
+
pageSize={100}
|
|
1383
|
+
itemsPerPage={[50, 100, 200]}
|
|
1384
|
+
/>
|
|
1385
|
+
);
|
|
1386
|
+
}
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
### Example 7: Disabled Rows and Custom Row Styles
|
|
1390
|
+
|
|
1391
|
+
```jsx
|
|
1392
|
+
function OrderGrid() {
|
|
1393
|
+
const [orders, setOrders] = useState([]);
|
|
1394
|
+
const [selected, setSelected] = useState([]);
|
|
1395
|
+
|
|
1396
|
+
// Disable completed and cancelled orders from selection
|
|
1397
|
+
const getDisabledRows = () => {
|
|
1398
|
+
return orders
|
|
1399
|
+
.filter(order => ['completed', 'cancelled'].includes(order.status))
|
|
1400
|
+
.map(order => order.orderId);
|
|
1401
|
+
};
|
|
1402
|
+
|
|
1403
|
+
const getRowStyle = ({ row }) => {
|
|
1404
|
+
const status = row.original.status;
|
|
1405
|
+
|
|
1406
|
+
switch (status) {
|
|
1407
|
+
case 'pending':
|
|
1408
|
+
return { backgroundColor: '#fff3cd' };
|
|
1409
|
+
case 'processing':
|
|
1410
|
+
return { backgroundColor: '#cfe2ff' };
|
|
1411
|
+
case 'completed':
|
|
1412
|
+
return { backgroundColor: '#d1e7dd', opacity: 0.7 };
|
|
1413
|
+
case 'cancelled':
|
|
1414
|
+
return { backgroundColor: '#f8d7da', opacity: 0.7 };
|
|
1415
|
+
default:
|
|
1416
|
+
return {};
|
|
1417
|
+
}
|
|
1418
|
+
};
|
|
1419
|
+
|
|
1420
|
+
const columns = [
|
|
1421
|
+
{ accessorKey: 'orderId', header: 'Order ID', type: 'text' },
|
|
1422
|
+
{ accessorKey: 'customer', header: 'Customer', type: 'textTitle' },
|
|
1423
|
+
{
|
|
1424
|
+
accessorKey: 'total',
|
|
1425
|
+
accessorFn: (row) => row.total ?? 0, // Ensure numeric value
|
|
1426
|
+
header: 'Total',
|
|
1427
|
+
type: 'currency'
|
|
1428
|
+
},
|
|
1429
|
+
{ accessorKey: 'status', header: 'Status', type: 'text' },
|
|
1430
|
+
{ accessorKey: 'orderDate', header: 'Order Date', type: 'datetime', isDateColumn: true },
|
|
1431
|
+
];
|
|
1432
|
+
|
|
1433
|
+
return (
|
|
1434
|
+
<DataGrid
|
|
1435
|
+
columns={columns}
|
|
1436
|
+
createRows={orders}
|
|
1437
|
+
rowKey="orderId"
|
|
1438
|
+
selectData={setSelected}
|
|
1439
|
+
disableRows={getDisabledRows()}
|
|
1440
|
+
getRowStyle={getRowStyle}
|
|
1441
|
+
gridHeight={600}
|
|
1442
|
+
/>
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
---
|
|
1448
|
+
|
|
1449
|
+
## API Reference
|
|
1450
|
+
|
|
1451
|
+
### Column Definition Object
|
|
1452
|
+
|
|
1453
|
+
```typescript
|
|
1454
|
+
interface ColumnDefinition {
|
|
1455
|
+
// Required
|
|
1456
|
+
accessorKey: string; // Key identifier for the column
|
|
1457
|
+
header: string; // Column header text
|
|
1458
|
+
|
|
1459
|
+
// Data Access (choose one)
|
|
1460
|
+
// Option 1: Direct property access (default when no accessorFn)
|
|
1461
|
+
// Option 2: Custom accessor function
|
|
1462
|
+
accessorFn?: (row: Object) => any; // Function to extract/compute value from row
|
|
1463
|
+
|
|
1464
|
+
// Type & Rendering
|
|
1465
|
+
type?: string; // Cell type for automatic formatting
|
|
1466
|
+
Cell?: React.Component; // Custom cell renderer (receives typeValue)
|
|
1467
|
+
cellClass?: string; // CSS class wrapper for cell content
|
|
1468
|
+
|
|
1469
|
+
// Filtering
|
|
1470
|
+
enableColumnFilter?: boolean; // Default: true
|
|
1471
|
+
enableColumnFilterModes?: boolean;// Default: true
|
|
1472
|
+
filterFn?: string | function; // Default: 'contains' (or undefined for dates)
|
|
1473
|
+
|
|
1474
|
+
// Sorting
|
|
1475
|
+
enableSorting?: boolean; // Default: true
|
|
1476
|
+
sortingFn?: string | function; // Default: 'basic' (or custom for dates)
|
|
1477
|
+
isDateColumn?: boolean; // Special date handling (default: false)
|
|
1478
|
+
|
|
1479
|
+
// Display
|
|
1480
|
+
enableResizing?: boolean; // Default: true
|
|
1481
|
+
grow?: boolean; // Column can grow (default: true)
|
|
1482
|
+
enableClickToCopy?: boolean; // Default: false
|
|
1483
|
+
enableColumnActions?: boolean; // Default: false
|
|
1484
|
+
|
|
1485
|
+
// Additional
|
|
1486
|
+
locale?: string; // Locale for formatting (e.g., 'en-US')
|
|
1487
|
+
onlyFlag?: boolean; // For countryFlag type
|
|
1488
|
+
columnDef?: object; // Additional metadata
|
|
1489
|
+
}
|
|
1490
|
+
```
|
|
1491
|
+
|
|
1492
|
+
### Action Object
|
|
1493
|
+
|
|
1494
|
+
```typescript
|
|
1495
|
+
interface ActionObject {
|
|
1496
|
+
// Required
|
|
1497
|
+
name: string; // Button label
|
|
1498
|
+
function: (selectedRows: Array, table?: Object) => void; // Click handler
|
|
1499
|
+
|
|
1500
|
+
// Display
|
|
1501
|
+
tooltip?: string; // Hover tooltip
|
|
1502
|
+
color?: 'blue' | 'red' | 'green' | 'yellow' | 'orange' | 'black' | 'grey' |
|
|
1503
|
+
'teal' | 'brown' | 'violet' | 'purple' | 'olive' | 'pink';
|
|
1504
|
+
icon?: string | React.Element; // Icon name or element
|
|
1505
|
+
|
|
1506
|
+
// Behavior
|
|
1507
|
+
selectionMode?: 'single' | 'multi' | 'always';
|
|
1508
|
+
confirmMessage?: string | React.Element;
|
|
1509
|
+
hasConfirmMessage?: boolean;
|
|
1510
|
+
disabled?: boolean;
|
|
1511
|
+
visible?: boolean; // Default: true
|
|
1512
|
+
|
|
1513
|
+
// Toggle mode
|
|
1514
|
+
toggle?: boolean;
|
|
1515
|
+
active?: boolean;
|
|
1516
|
+
|
|
1517
|
+
// Other
|
|
1518
|
+
key?: string; // Unique React key
|
|
1519
|
+
}
|
|
1520
|
+
```
|
|
1521
|
+
|
|
1522
|
+
### Extra Action Object
|
|
1523
|
+
|
|
1524
|
+
```typescript
|
|
1525
|
+
interface ExtraActionObject {
|
|
1526
|
+
// Required
|
|
1527
|
+
function: () => void; // Click handler
|
|
1528
|
+
content: string | React.Element; // Button content/label
|
|
1529
|
+
|
|
1530
|
+
// Display
|
|
1531
|
+
tooltip?: string; // Hover tooltip
|
|
1532
|
+
icon?: string | React.Element; // Icon name or element
|
|
1533
|
+
style?: React.CSSProperties; // Custom button styles
|
|
1534
|
+
propsButton?: object; // Additional Semantic UI Button props
|
|
1535
|
+
}
|
|
1536
|
+
```
|
|
1537
|
+
|
|
1538
|
+
### Data Row Object
|
|
1539
|
+
|
|
1540
|
+
```typescript
|
|
1541
|
+
interface DataRow {
|
|
1542
|
+
[rowKey: string]: any; // Unique identifier (required)
|
|
1543
|
+
[key: string]: any; // Other data fields
|
|
1544
|
+
|
|
1545
|
+
// Optional: For hierarchical data
|
|
1546
|
+
subRows?: Array<DataRow>;
|
|
1547
|
+
isSubRow?: boolean;
|
|
1548
|
+
}
|
|
1549
|
+
```
|
|
1550
|
+
|
|
1551
|
+
---
|
|
1552
|
+
|
|
1553
|
+
## Performance Tips
|
|
1554
|
+
|
|
1555
|
+
### 1. Use Virtualization for Large Datasets
|
|
1556
|
+
```jsx
|
|
1557
|
+
// For 1000+ rows
|
|
1558
|
+
enableVirtualization={true}
|
|
1559
|
+
```
|
|
1560
|
+
|
|
1561
|
+
### 2. Optimize Row Height and Compact Mode
|
|
1562
|
+
```jsx
|
|
1563
|
+
// Smaller rows = more visible data
|
|
1564
|
+
rowHeight={40}
|
|
1565
|
+
enableCompactStyleMode={true}
|
|
1566
|
+
fontSize={12}
|
|
1567
|
+
```
|
|
1568
|
+
|
|
1569
|
+
### 3. Disable Unused Features
|
|
1570
|
+
```jsx
|
|
1571
|
+
// Reduce overhead by disabling features you don't need
|
|
1572
|
+
enableDensityToggle={false}
|
|
1573
|
+
enableFullScreenToggle={false}
|
|
1574
|
+
enableGlobalFilter={false}
|
|
1575
|
+
enableColumnFilterModes={false}
|
|
1576
|
+
```
|
|
1577
|
+
|
|
1578
|
+
### 4. Limit Initial Page Size
|
|
1579
|
+
```jsx
|
|
1580
|
+
// Don't render too many rows initially
|
|
1581
|
+
pageSize={50} // Instead of 150
|
|
1582
|
+
itemsPerPage={[25, 50, 100]}
|
|
1583
|
+
```
|
|
1584
|
+
|
|
1585
|
+
### 5. Pre-select Rows Carefully
|
|
1586
|
+
```jsx
|
|
1587
|
+
// Only include necessary IDs
|
|
1588
|
+
selectedIds={criticalIds} // Instead of selecting all rows
|
|
1589
|
+
```
|
|
1590
|
+
|
|
1591
|
+
### 6. Optimize Custom Cell Renderers
|
|
1592
|
+
```jsx
|
|
1593
|
+
// Use typeValue when available
|
|
1594
|
+
const MyCell = ({ typeValue, cell }) => {
|
|
1595
|
+
return typeValue || cell.getValue(); // Prefer pre-formatted typeValue
|
|
1596
|
+
};
|
|
1597
|
+
|
|
1598
|
+
// Memoize expensive computations
|
|
1599
|
+
const ExpensiveCell = React.memo(({ cell }) => {
|
|
1600
|
+
const processedValue = useMemo(() => expensiveComputation(cell.getValue()), [cell]);
|
|
1601
|
+
return <div>{processedValue}</div>;
|
|
1602
|
+
});
|
|
1603
|
+
```
|
|
1604
|
+
|
|
1605
|
+
### 7. Keep accessorFn Lightweight
|
|
1606
|
+
```jsx
|
|
1607
|
+
// Bad - Complex computation on every render/filter/sort
|
|
1608
|
+
accessorFn: (row) => {
|
|
1609
|
+
return expensiveCalculation(row.data);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
// Good - Simple, fast operations
|
|
1613
|
+
accessorFn: (row) => row.data?.value ?? 0
|
|
1614
|
+
|
|
1615
|
+
// Better - Pre-process data before passing to grid
|
|
1616
|
+
const processedData = rawData.map(row => ({
|
|
1617
|
+
...row,
|
|
1618
|
+
computedValue: expensiveCalculation(row.data)
|
|
1619
|
+
}));
|
|
1620
|
+
```
|
|
1621
|
+
|
|
1622
|
+
### 8. Use Column Visibility Wisely
|
|
1623
|
+
```jsx
|
|
1624
|
+
// Hide columns that aren't immediately needed
|
|
1625
|
+
columnVisibilityState={{
|
|
1626
|
+
metadata: false,
|
|
1627
|
+
internalId: false,
|
|
1628
|
+
debugInfo: false
|
|
1629
|
+
}}
|
|
1630
|
+
```
|
|
1631
|
+
|
|
1632
|
+
### 9. Implement Efficient Row Styling
|
|
1633
|
+
```jsx
|
|
1634
|
+
// Keep getRowStyle lightweight
|
|
1635
|
+
getRowStyle={({ row }) => {
|
|
1636
|
+
// Simple conditional - avoid heavy computation
|
|
1637
|
+
return row.original.isHighlighted ? { backgroundColor: '#fffacd' } : {};
|
|
1638
|
+
}}
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1641
|
+
### 10. Batch State Updates
|
|
1642
|
+
```jsx
|
|
1643
|
+
// Instead of multiple state updates, batch them
|
|
1644
|
+
const handleMultipleChanges = () => {
|
|
1645
|
+
// Use a single state update with derived values
|
|
1646
|
+
setData(prevData => processAndUpdate(prevData));
|
|
1647
|
+
};
|
|
1648
|
+
```
|
|
1649
|
+
|
|
1650
|
+
### 11. Leverage React's Built-in Optimizations
|
|
1651
|
+
```jsx
|
|
1652
|
+
// Use keys properly for subRows
|
|
1653
|
+
const data = subRowData.map((item, index) => ({
|
|
1654
|
+
...item,
|
|
1655
|
+
id: `${parentId}.${index}` // Stable, unique keys
|
|
1656
|
+
}));
|
|
1657
|
+
```
|
|
1658
|
+
|
|
1659
|
+
---
|
|
1660
|
+
|
|
1661
|
+
## Browser Support
|
|
1662
|
+
|
|
1663
|
+
- **Chrome:** Latest version (recommended)
|
|
1664
|
+
- **Firefox:** Latest version
|
|
1665
|
+
- **Safari:** Latest version
|
|
1666
|
+
- **Edge:** Latest version (Chromium-based)
|
|
1667
|
+
|
|
1668
|
+
### CSS Requirements
|
|
1669
|
+
- CSS Grid support (all modern browsers)
|
|
1670
|
+
- CSS Sticky positioning for fixed headers
|
|
1671
|
+
- Flexbox for layouts
|
|
1672
|
+
|
|
1673
|
+
---
|
|
1674
|
+
|
|
1675
|
+
## Troubleshooting
|
|
1676
|
+
|
|
1677
|
+
### Common Issues
|
|
1678
|
+
|
|
1679
|
+
#### **Issue: Rows not selecting when clicked**
|
|
1680
|
+
|
|
1681
|
+
**Symptoms:** Clicking rows doesn't select them, checkboxes don't appear
|
|
1682
|
+
|
|
1683
|
+
**Solutions:**
|
|
1684
|
+
- Verify `disableSelect={false}` (this is the default)
|
|
1685
|
+
- Ensure `selectData` callback is provided
|
|
1686
|
+
- Check that `rowKey` matches your data's unique identifier property
|
|
1687
|
+
- Verify rows aren't in the `disableRows` array
|
|
1688
|
+
|
|
1689
|
+
```jsx
|
|
1690
|
+
// Correct configuration
|
|
1691
|
+
<DataGrid
|
|
1692
|
+
rowKey="id" // Matches data[0].id
|
|
1693
|
+
selectData={handleSelection} // Required callback
|
|
1694
|
+
disableSelect={false} // Optional - default is false
|
|
1695
|
+
disableRows={[]} // No disabled rows
|
|
1696
|
+
/>
|
|
1697
|
+
```
|
|
1698
|
+
|
|
1699
|
+
#### **Issue: Date columns not sorting correctly**
|
|
1700
|
+
|
|
1701
|
+
**Symptoms:** Dates sort alphabetically instead of chronologically
|
|
1702
|
+
|
|
1703
|
+
**Solutions:**
|
|
1704
|
+
- Set `isDateColumn={true}` on date columns
|
|
1705
|
+
- Ensure date values are in valid ISO 8601 format (`YYYY-MM-DD` or `YYYY-MM-DDTHH:mm:ss`)
|
|
1706
|
+
- Check that date strings are parseable by JavaScript `Date` constructor
|
|
1707
|
+
|
|
1708
|
+
```jsx
|
|
1709
|
+
// Correct date column configuration
|
|
1710
|
+
{
|
|
1711
|
+
accessorKey: 'createdAt',
|
|
1712
|
+
header: 'Created Date',
|
|
1713
|
+
type: 'date',
|
|
1714
|
+
isDateColumn: true // Enables date-aware sorting
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
// Data format
|
|
1718
|
+
const data = [
|
|
1719
|
+
{ id: 1, createdAt: '2025-01-15' }, // ISO 8601 format
|
|
1720
|
+
{ id: 2, createdAt: '2024-12-20' },
|
|
1721
|
+
];
|
|
1722
|
+
```
|
|
1723
|
+
|
|
1724
|
+
#### **Issue: Fixed headers not working**
|
|
1725
|
+
|
|
1726
|
+
**Symptoms:** Headers scroll with content instead of staying fixed
|
|
1727
|
+
|
|
1728
|
+
**Solutions:**
|
|
1729
|
+
- Set `enableFixedHeader={true}` (default is true)
|
|
1730
|
+
- Ensure `gridHeight` is set to a specific numeric value or CSS string
|
|
1731
|
+
- Do not use `gridHeight="fit-content"` with fixed headers
|
|
1732
|
+
- Check for CSS conflicts with `grid-sticky-header` class
|
|
1733
|
+
|
|
1734
|
+
```jsx
|
|
1735
|
+
// Correct fixed header configuration
|
|
1736
|
+
<DataGrid
|
|
1737
|
+
enableFixedHeader={true}
|
|
1738
|
+
gridHeight={600} // Or "80vh", not "fit-content"
|
|
1739
|
+
/>
|
|
1740
|
+
```
|
|
1741
|
+
|
|
1742
|
+
#### **Issue: Fixed actions toolbar not sticking**
|
|
1743
|
+
|
|
1744
|
+
**Symptoms:** Action buttons scroll instead of staying at top
|
|
1745
|
+
|
|
1746
|
+
**Solutions:**
|
|
1747
|
+
- Enable both `enableFixedHeader={true}` and `enableFixedActions={true}`
|
|
1748
|
+
- Verify `gridHeight` is set to a specific value
|
|
1749
|
+
- Check for CSS conflicts with `grid-sticky-actions` class
|
|
1750
|
+
|
|
1751
|
+
```jsx
|
|
1752
|
+
<DataGrid
|
|
1753
|
+
enableFixedHeader={true}
|
|
1754
|
+
enableFixedActions={true}
|
|
1755
|
+
gridHeight={700}
|
|
1756
|
+
/>
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1759
|
+
#### **Issue: Selection state not syncing with parent component**
|
|
1760
|
+
|
|
1761
|
+
**Symptoms:** External state doesn't match grid selection
|
|
1762
|
+
|
|
1763
|
+
**Solutions:**
|
|
1764
|
+
- Use the `selectedIds` prop to control selection from parent
|
|
1765
|
+
- Component automatically syncs when `selectedIds` prop changes
|
|
1766
|
+
- Ensure `rowKey` values in `selectedIds` match data
|
|
1767
|
+
|
|
1768
|
+
```jsx
|
|
1769
|
+
const [externalSelection, setExternalSelection] = useState([1, 5, 10]);
|
|
1770
|
+
|
|
1771
|
+
<DataGrid
|
|
1772
|
+
selectedIds={externalSelection} // Controlled selection
|
|
1773
|
+
selectData={(rows) => {
|
|
1774
|
+
const ids = rows.map(r => r.id);
|
|
1775
|
+
setExternalSelection(ids);
|
|
1776
|
+
}}
|
|
1777
|
+
/>
|
|
1778
|
+
```
|
|
1779
|
+
|
|
1780
|
+
#### **Issue: Export buttons not appearing**
|
|
1781
|
+
|
|
1782
|
+
**Symptoms:** Excel/PDF export buttons are not visible
|
|
1783
|
+
|
|
1784
|
+
**Solutions:**
|
|
1785
|
+
- Set `hasExcelExport={true}` and/or `hasPdfExport={true}`
|
|
1786
|
+
- Check that `disableSideActions={false}` (default)
|
|
1787
|
+
- Ensure toolbar has space (not too many actions)
|
|
1788
|
+
- Verify `enableTopToolbar={true}` (default)
|
|
1789
|
+
|
|
1790
|
+
```jsx
|
|
1791
|
+
<DataGrid
|
|
1792
|
+
hasExcelExport={true}
|
|
1793
|
+
hasPdfExport={true}
|
|
1794
|
+
enableTopToolbar={true}
|
|
1795
|
+
disableSideActions={false}
|
|
1796
|
+
/>
|
|
1797
|
+
```
|
|
1798
|
+
|
|
1799
|
+
#### **Issue: Type formatter not working**
|
|
1800
|
+
|
|
1801
|
+
**Symptoms:** Column values appear as raw data instead of formatted
|
|
1802
|
+
|
|
1803
|
+
**Solutions:**
|
|
1804
|
+
- Verify column has `type` property defined
|
|
1805
|
+
- Check that `type` value exists in `DEFAULT_CELL_TYPES` (e.g., 'text', 'date', 'currency', 'email')
|
|
1806
|
+
- Ensure data values are in correct format for the type
|
|
1807
|
+
- Check browser console for errors
|
|
1808
|
+
|
|
1809
|
+
```jsx
|
|
1810
|
+
// Correct type configuration
|
|
1811
|
+
{
|
|
1812
|
+
accessorKey: 'price',
|
|
1813
|
+
header: 'Price',
|
|
1814
|
+
type: 'currency' // Must match a valid type
|
|
1815
|
+
}
|
|
1816
|
+
```
|
|
1817
|
+
|
|
1818
|
+
#### **Issue: Custom Cell component not receiving typeValue**
|
|
1819
|
+
|
|
1820
|
+
**Symptoms:** `typeValue` prop is undefined in custom Cell
|
|
1821
|
+
|
|
1822
|
+
**Solutions:**
|
|
1823
|
+
- Verify column has both `type` AND `Cell` defined
|
|
1824
|
+
- Check that `type` matches a key in `DEFAULT_CELL_TYPES`
|
|
1825
|
+
- `typeValue` only exists when type formatter is applied
|
|
1826
|
+
|
|
1827
|
+
```jsx
|
|
1828
|
+
// Correct configuration for typeValue
|
|
1829
|
+
const CustomCell = ({ typeValue, cell }) => {
|
|
1830
|
+
console.log(typeValue); // Will be defined
|
|
1831
|
+
return <div>{typeValue}</div>;
|
|
1832
|
+
};
|
|
1833
|
+
|
|
1834
|
+
{
|
|
1835
|
+
accessorKey: 'amount',
|
|
1836
|
+
type: 'currency', // Required for typeValue
|
|
1837
|
+
Cell: CustomCell // Will receive typeValue
|
|
1838
|
+
}
|
|
1839
|
+
```
|
|
1840
|
+
|
|
1841
|
+
#### **Issue: accessorFn not being used for filtering/sorting**
|
|
1842
|
+
|
|
1843
|
+
**Symptoms:** Filters and sorts use raw data instead of accessorFn result
|
|
1844
|
+
|
|
1845
|
+
**Solutions:**
|
|
1846
|
+
- Verify `accessorFn` is defined correctly
|
|
1847
|
+
- The returned value from `accessorFn` is what gets filtered/sorted
|
|
1848
|
+
- For complex objects, ensure `accessorFn` returns a simple value
|
|
1849
|
+
|
|
1850
|
+
```jsx
|
|
1851
|
+
// Bad - Returns object (hard to filter/sort)
|
|
1852
|
+
accessorFn: (row) => ({ value: row.data })
|
|
1853
|
+
|
|
1854
|
+
// Good - Returns simple value
|
|
1855
|
+
accessorFn: (row) => row.data?.value ?? 0
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
#### **Issue: Virtualization causing scroll issues**
|
|
1859
|
+
|
|
1860
|
+
**Symptoms:** Jerky scrolling, rows not rendering, blank spaces
|
|
1861
|
+
|
|
1862
|
+
**Solutions:**
|
|
1863
|
+
- Ensure `rowHeight` is set accurately
|
|
1864
|
+
- Don't use dynamic row heights with virtualization
|
|
1865
|
+
- Check that `enableVirtualization={true}` is actually needed (only for 1000+ rows)
|
|
1866
|
+
- Verify data doesn't change reference on every render
|
|
1867
|
+
|
|
1868
|
+
```jsx
|
|
1869
|
+
// Good for virtualization
|
|
1870
|
+
<DataGrid
|
|
1871
|
+
enableVirtualization={true}
|
|
1872
|
+
rowHeight={40} // Fixed height
|
|
1873
|
+
createRows={stableDataReference} // Don't recreate array
|
|
1874
|
+
/>
|
|
1875
|
+
```
|
|
1876
|
+
|
|
1877
|
+
#### **Issue: Actions not enabling/disabling correctly**
|
|
1878
|
+
|
|
1879
|
+
**Symptoms:** Action buttons stay disabled when rows are selected
|
|
1880
|
+
|
|
1881
|
+
**Solutions:**
|
|
1882
|
+
- Check `selectionMode` setting ('single', 'multi', 'always')
|
|
1883
|
+
- Verify `disabled` prop isn't set to true
|
|
1884
|
+
- Ensure rows are actually being selected (check `selectData` callback)
|
|
1885
|
+
|
|
1886
|
+
```jsx
|
|
1887
|
+
actions={[
|
|
1888
|
+
{
|
|
1889
|
+
name: 'Edit',
|
|
1890
|
+
selectionMode: 'single', // Requires exactly 1 row
|
|
1891
|
+
function: handleEdit,
|
|
1892
|
+
disabled: false // Not manually disabled
|
|
1893
|
+
}
|
|
1894
|
+
]}
|
|
1895
|
+
```
|
|
1896
|
+
|
|
1897
|
+
#### **Issue: Hierarchical data (subRows) not working**
|
|
1898
|
+
|
|
1899
|
+
**Symptoms:** SubRows don't expand or aren't selectable
|
|
1900
|
+
|
|
1901
|
+
**Solutions:**
|
|
1902
|
+
- Set `hasSubRows={true}`
|
|
1903
|
+
- Set `enableExpanding={true}` to show expand icons
|
|
1904
|
+
- Ensure data has correct `subRows` structure
|
|
1905
|
+
- SubRow IDs should follow pattern: `"parentId.index"`
|
|
1906
|
+
```jsx
|
|
1907
|
+
const hierarchicalData = [
|
|
1908
|
+
{
|
|
1909
|
+
id: 1,
|
|
1910
|
+
name: 'Parent',
|
|
1911
|
+
subRows: [
|
|
1912
|
+
{ id: '1.1', name: 'Child 1' },
|
|
1913
|
+
{ id: '1.2', name: 'Child 2' }
|
|
1914
|
+
]
|
|
1915
|
+
}
|
|
1916
|
+
];
|
|
1917
|
+
|
|
1918
|
+
<DataGrid
|
|
1919
|
+
hasSubRows={true}
|
|
1920
|
+
enableExpanding={true}
|
|
1921
|
+
createRows={hierarchicalData}
|
|
1922
|
+
/>
|
|
1923
|
+
```
|
|
1924
|
+
|
|
1925
|
+
#### **Issue: Cache update button not appearing**
|
|
1926
|
+
|
|
1927
|
+
**Symptoms:** Cache/refresh button is not visible
|
|
1928
|
+
|
|
1929
|
+
**Solutions:**
|
|
1930
|
+
- Provide `updateCache` function prop
|
|
1931
|
+
- Optionally set `cacheUpdateText` for tooltip
|
|
1932
|
+
- Button only appears when `updateCache` is defined
|
|
1933
|
+
|
|
1934
|
+
```jsx
|
|
1935
|
+
<DataGrid
|
|
1936
|
+
updateCache={() => fetchLatestData()}
|
|
1937
|
+
cacheUpdateText="Refresh from server"
|
|
1938
|
+
cacheUpdating={isLoading}
|
|
1939
|
+
/>
|
|
1940
|
+
```
|
|
1941
|
+
|
|
1942
|
+
#### **Issue: Row styles not applying**
|
|
1943
|
+
|
|
1944
|
+
**Symptoms:** `getRowStyle` returns styles but they don't appear
|
|
1945
|
+
|
|
1946
|
+
**Solutions:**
|
|
1947
|
+
- Check that returned object contains valid CSS properties
|
|
1948
|
+
- Verify function is actually being called
|
|
1949
|
+
- CSS specificity might be overriding - use `!important` if needed
|
|
1950
|
+
- Check browser console for CSS errors
|
|
1951
|
+
|
|
1952
|
+
```jsx
|
|
1953
|
+
getRowStyle={({ row }) => {
|
|
1954
|
+
console.log('Styling row:', row.id); // Debug
|
|
1955
|
+
return {
|
|
1956
|
+
backgroundColor: row.original.isHighlighted ? '#fffacd !important' : 'white'
|
|
1957
|
+
};
|
|
1958
|
+
}}
|
|
1959
|
+
```
|
|
1960
|
+
|
|
1961
|
+
#### **Issue: Filters not working**
|
|
1962
|
+
|
|
1963
|
+
**Symptoms:** Column filters don't filter data
|
|
1964
|
+
|
|
1965
|
+
**Solutions:**
|
|
1966
|
+
- Verify `enableColumnFilter={true}` on columns (default)
|
|
1967
|
+
- Check that `filterFn` is valid
|
|
1968
|
+
- Ensure data values match filter input type
|
|
1969
|
+
- If using `accessorFn`, ensure it returns filterable values
|
|
1970
|
+
|
|
1971
|
+
```jsx
|
|
1972
|
+
{
|
|
1973
|
+
accessorKey: 'status',
|
|
1974
|
+
header: 'Status',
|
|
1975
|
+
enableColumnFilter: true,
|
|
1976
|
+
filterFn: 'contains' // or 'equals', 'startsWith', etc.
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
// With accessorFn
|
|
1980
|
+
{
|
|
1981
|
+
accessorKey: 'papers',
|
|
1982
|
+
accessorFn: (row) => row.numberPapers?.value ?? 0, // Returns number for filtering
|
|
1983
|
+
header: 'Papers',
|
|
1984
|
+
type: 'integer'
|
|
1985
|
+
}
|
|
1986
|
+
```
|
|
1987
|
+
|
|
1988
|
+
---
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
## Important Notes
|
|
1992
|
+
|
|
1993
|
+
### Row Selection Behavior
|
|
1994
|
+
- **Disabled Select:** When `disableSelect={true}` hide the selection checkbox/radio and cannot be selected
|
|
1995
|
+
- **Single selection mode:** When `enableMultiRowSelection={false}`, clicking a row deselects all others
|
|
1996
|
+
- **Multi-selection:** Use checkboxes when `enableMultiRowSelection={true}`
|
|
1997
|
+
- **Selection state:** Controlled via `rowSelection` state and `selectData` callback
|
|
1998
|
+
|
|
1999
|
+
### Fixed Header and Actions
|
|
2000
|
+
- `enableFixedHeader` uses CSS `position: sticky` on column headers
|
|
2001
|
+
- `enableFixedActions` (requires `enableFixedHeader={true}`) also pins the toolbar
|
|
2002
|
+
- Both require `gridHeight` to be set to a specific value (not 'fit-content')
|
|
2003
|
+
- CSS classes: `grid-sticky-header` and `grid-sticky-actions`
|
|
2004
|
+
|
|
2005
|
+
### Date Columns
|
|
2006
|
+
- Use `type: 'date'` for date-only display (no time)
|
|
2007
|
+
- Use `type: 'datetime'` for full datetime display
|
|
2008
|
+
- Default locale is 'pt-PT' - override with `locale` prop on column
|
|
2009
|
+
- Date values should be ISO 8601 format for best results
|
|
2010
|
+
|
|
2011
|
+
### accessorFn Performance
|
|
2012
|
+
- `accessorFn` is called for **every cell render, filter operation, and sort operation**
|
|
2013
|
+
- Keep computations lightweight
|
|
2014
|
+
- Avoid creating new objects/arrays in `accessorFn`
|
|
2015
|
+
- Pre-process complex data before passing to the grid when possible
|
|
2016
|
+
- The returned value is what gets filtered and sorted
|
|
2017
|
+
|
|
2018
|
+
### LocalizationProvider
|
|
2019
|
+
- Component is wrapped with MUI's `LocalizationProvider` using `AdapterDateFns`
|
|
2020
|
+
- Required for date picker functionality in filters
|
|
2021
|
+
- No need to add this provider in your own code
|
|
2022
|
+
|
|
2023
|
+
### SubRows and Hierarchical Data
|
|
2024
|
+
- SubRow IDs follow pattern: `"parentId.subRowIndex"` (e.g., "1.0", "1.1")
|
|
2025
|
+
- Selection works on both parent and child rows
|
|
2026
|
+
- Visual depth indicated by background color and padding
|
|
2027
|
+
- Requires `hasSubRows={true}` to enable
|
|
2028
|
+
|
|
2029
|
+
### Performance Considerations
|
|
2030
|
+
- Virtualization is recommended for 1000+ rows
|
|
2031
|
+
- Compact style mode reduces render overhead
|
|
2032
|
+
- Custom cell components should be memoized when possible
|
|
2033
|
+
- Avoid recreating data arrays on every render
|
|
2034
|
+
- Keep `accessorFn` computations lightweight
|
|
2035
|
+
|
|
2036
|
+
### Browser Storage
|
|
2037
|
+
- Component does NOT use localStorage or sessionStorage
|
|
2038
|
+
- All state is maintained in React state (useState)
|
|
2039
|
+
- Selection state is ephemeral unless managed by parent
|
|
2040
|
+
|
|
2041
|
+
---
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
## Dependencies
|
|
2045
|
+
|
|
2046
|
+
This component requires the following peer dependencies:
|
|
2047
|
+
|
|
2048
|
+
### Core Dependencies
|
|
2049
|
+
- **react** (^16.8.0 || ^17.0.0 || ^18.0.0) - React framework
|
|
2050
|
+
- **prop-types** - Runtime type checking for React props
|
|
2051
|
+
- **material-react-table** - Core table functionality and hooks
|
|
2052
|
+
- **@mui/material** - Material UI components
|
|
2053
|
+
- **@mui/x-date-pickers** - Date picker components for filters
|
|
2054
|
+
- **date-fns** - Date manipulation and formatting
|
|
2055
|
+
- **semantic-ui-react** - Semantic UI React components for buttons and icons
|
|
2056
|
+
- **bootstrap** - Base CSS framework
|
|
2057
|
+
- **semantic-ui-css** - Semantic UI CSS styles
|
|
2058
|
+
|
|
2059
|
+
### Version Compatibility
|
|
2060
|
+
```json
|
|
2061
|
+
{
|
|
2062
|
+
"peerDependencies": {
|
|
2063
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
2064
|
+
"material-react-table": "^2.0.0",
|
|
2065
|
+
"@mui/material": "^5.0.0",
|
|
2066
|
+
"semantic-ui-react": "^2.0.0"
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
```
|
|
2070
|
+
|
|
2071
|
+
### Built With
|
|
2072
|
+
- [Material React Table](https://www.material-react-table.com/) - Advanced table features
|
|
2073
|
+
- [MUI (Material-UI)](https://mui.com/) - UI components and theming
|
|
2074
|
+
- [Semantic UI React](https://react.semantic-ui.com/) - Button and icon components
|
|
2075
|
+
- [Bootstrap](https://getbootstrap.com/) - CSS utilities
|
|
2076
|
+
- [date-fns](https://date-fns.org/) - Modern JavaScript date utility library
|
|
2077
|
+
|
|
2078
|
+
---
|
|
2079
|
+
|
|
2080
|
+
## License
|
|
2081
|
+
|
|
2082
|
+
ISC
|
|
2083
|
+
|
|
2084
|
+
---
|