@lminii/material-react-table-mcp 4.0.1
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 +68 -0
- package/data/MIGRATION.md +136 -0
- package/data/api.json +5379 -0
- package/data/examples/advanced.js +215 -0
- package/data/examples/advanced.tsx +309 -0
- package/data/examples/aggregation-and-grouping.js +116 -0
- package/data/examples/aggregation-and-grouping.tsx +153 -0
- package/data/examples/aggregation-multi.js +89 -0
- package/data/examples/aggregation-multi.tsx +105 -0
- package/data/examples/alternate-column-filtering.js +38 -0
- package/data/examples/alternate-column-filtering.tsx +49 -0
- package/data/examples/alternate-detail-panel.js +65 -0
- package/data/examples/alternate-detail-panel.tsx +81 -0
- package/data/examples/alternate-pagination.js +17 -0
- package/data/examples/alternate-pagination.tsx +23 -0
- package/data/examples/basic.js +86 -0
- package/data/examples/basic.tsx +109 -0
- package/data/examples/chart-detail-panel.js +69 -0
- package/data/examples/chart-detail-panel.tsx +89 -0
- package/data/examples/column-actions-space.js +34 -0
- package/data/examples/column-actions-space.tsx +44 -0
- package/data/examples/column-alignment.js +58 -0
- package/data/examples/column-alignment.tsx +70 -0
- package/data/examples/custom-column-actions.js +74 -0
- package/data/examples/custom-column-actions.tsx +109 -0
- package/data/examples/custom-column-filtering-ui.js +59 -0
- package/data/examples/custom-column-filtering-ui.tsx +89 -0
- package/data/examples/custom-headless.js +85 -0
- package/data/examples/custom-headless.tsx +125 -0
- package/data/examples/custom-top-toolbar.js +60 -0
- package/data/examples/custom-top-toolbar.tsx +88 -0
- package/data/examples/customize-display-columns.js +72 -0
- package/data/examples/customize-display-columns.tsx +85 -0
- package/data/examples/customize-filter-components.js +78 -0
- package/data/examples/customize-filter-components.tsx +101 -0
- package/data/examples/customize-filter-modes.js +59 -0
- package/data/examples/customize-filter-modes.tsx +73 -0
- package/data/examples/customize-filter-variants.js +98 -0
- package/data/examples/customize-filter-variants.tsx +116 -0
- package/data/examples/customize-global-filter-component.js +37 -0
- package/data/examples/customize-global-filter-component.tsx +52 -0
- package/data/examples/customize-remove-column-grouping.js +75 -0
- package/data/examples/customize-remove-column-grouping.tsx +94 -0
- package/data/examples/customize-row-selection.js +43 -0
- package/data/examples/customize-row-selection.tsx +54 -0
- package/data/examples/customize-table-styles.js +81 -0
- package/data/examples/customize-table-styles.tsx +100 -0
- package/data/examples/disable-column-actions.js +26 -0
- package/data/examples/disable-column-actions.tsx +37 -0
- package/data/examples/disable-column-hiding.js +74 -0
- package/data/examples/disable-column-hiding.tsx +90 -0
- package/data/examples/disable-density-toggle.js +37 -0
- package/data/examples/disable-density-toggle.tsx +49 -0
- package/data/examples/dynamic-columns.js +124 -0
- package/data/examples/dynamic-columns.tsx +189 -0
- package/data/examples/editing-crud-cell.js +288 -0
- package/data/examples/editing-crud-cell.tsx +377 -0
- package/data/examples/editing-crud-modal.js +275 -0
- package/data/examples/editing-crud-modal.tsx +370 -0
- package/data/examples/editing-crud-row.js +255 -0
- package/data/examples/editing-crud-row.tsx +333 -0
- package/data/examples/editing-crud-table.js +280 -0
- package/data/examples/editing-crud-table.tsx +369 -0
- package/data/examples/editing-crud-tree.js +328 -0
- package/data/examples/editing-crud-tree.tsx +416 -0
- package/data/examples/enable-cell-actions.js +52 -0
- package/data/examples/enable-cell-actions.tsx +76 -0
- package/data/examples/enable-click-to-copy.js +33 -0
- package/data/examples/enable-click-to-copy.tsx +39 -0
- package/data/examples/enable-column-grouping.js +69 -0
- package/data/examples/enable-column-grouping.tsx +120 -0
- package/data/examples/enable-column-ordering.js +37 -0
- package/data/examples/enable-column-ordering.tsx +48 -0
- package/data/examples/enable-column-pinning.js +58 -0
- package/data/examples/enable-column-pinning.tsx +69 -0
- package/data/examples/enable-column-resizing.js +45 -0
- package/data/examples/enable-column-resizing.tsx +56 -0
- package/data/examples/enable-column-virtualization.js +19 -0
- package/data/examples/enable-column-virtualization.tsx +27 -0
- package/data/examples/enable-detail-panel-conditionally.js +61 -0
- package/data/examples/enable-detail-panel-conditionally.tsx +78 -0
- package/data/examples/enable-detail-panel-virtualized.js +64 -0
- package/data/examples/enable-detail-panel-virtualized.tsx +80 -0
- package/data/examples/enable-expanding-tree.js +87 -0
- package/data/examples/enable-expanding-tree.tsx +110 -0
- package/data/examples/enable-filter-facet-values.js +52 -0
- package/data/examples/enable-filter-facet-values.tsx +65 -0
- package/data/examples/enable-row-dragging.js +102 -0
- package/data/examples/enable-row-dragging.tsx +137 -0
- package/data/examples/enable-row-numbers-original.js +37 -0
- package/data/examples/enable-row-numbers-original.tsx +48 -0
- package/data/examples/enable-row-numbers-static.js +37 -0
- package/data/examples/enable-row-numbers-static.tsx +48 -0
- package/data/examples/enable-row-ordering.js +40 -0
- package/data/examples/enable-row-ordering.tsx +57 -0
- package/data/examples/enable-row-pinning-select.js +64 -0
- package/data/examples/enable-row-pinning-select.tsx +76 -0
- package/data/examples/enable-row-pinning-static.js +39 -0
- package/data/examples/enable-row-pinning-static.tsx +50 -0
- package/data/examples/enable-row-pinning-sticky.js +57 -0
- package/data/examples/enable-row-pinning-sticky.tsx +69 -0
- package/data/examples/enable-row-selection.js +71 -0
- package/data/examples/enable-row-selection.tsx +96 -0
- package/data/examples/enable-row-virtualization.js +85 -0
- package/data/examples/enable-row-virtualization.tsx +101 -0
- package/data/examples/enable-sticky-header.js +47 -0
- package/data/examples/enable-sticky-header.tsx +59 -0
- package/data/examples/expanding-tree-expanded.js +98 -0
- package/data/examples/expanding-tree-expanded.tsx +121 -0
- package/data/examples/expanding-tree-flat-parse.js +102 -0
- package/data/examples/expanding-tree-flat-parse.tsx +125 -0
- package/data/examples/expanding-tree-root-expanded.js +120 -0
- package/data/examples/expanding-tree-root-expanded.tsx +151 -0
- package/data/examples/export-to-csv.js +84 -0
- package/data/examples/export-to-csv.tsx +114 -0
- package/data/examples/export-to-pdf.js +76 -0
- package/data/examples/export-to-pdf.tsx +104 -0
- package/data/examples/external-toolbar.js +82 -0
- package/data/examples/external-toolbar.tsx +108 -0
- package/data/examples/font-awesome-icons.js +62 -0
- package/data/examples/font-awesome-icons.tsx +106 -0
- package/data/examples/infinite-scrolling.js +137 -0
- package/data/examples/infinite-scrolling.tsx +208 -0
- package/data/examples/lazy-detail-panel.js +164 -0
- package/data/examples/lazy-detail-panel.tsx +262 -0
- package/data/examples/lazy-sub-rows.js +118 -0
- package/data/examples/lazy-sub-rows.tsx +190 -0
- package/data/examples/linear-progress.js +48 -0
- package/data/examples/linear-progress.tsx +66 -0
- package/data/examples/loading.js +34 -0
- package/data/examples/loading.tsx +50 -0
- package/data/examples/localization-i18n-ar.js +40 -0
- package/data/examples/localization-i18n-ar.tsx +65 -0
- package/data/examples/localization-i18n-az.js +38 -0
- package/data/examples/localization-i18n-az.tsx +60 -0
- package/data/examples/localization-i18n-bg.js +38 -0
- package/data/examples/localization-i18n-bg.tsx +60 -0
- package/data/examples/localization-i18n-cs.js +38 -0
- package/data/examples/localization-i18n-cs.tsx +60 -0
- package/data/examples/localization-i18n-da.js +38 -0
- package/data/examples/localization-i18n-da.tsx +60 -0
- package/data/examples/localization-i18n-de.js +38 -0
- package/data/examples/localization-i18n-de.tsx +60 -0
- package/data/examples/localization-i18n-el.js +38 -0
- package/data/examples/localization-i18n-el.tsx +60 -0
- package/data/examples/localization-i18n-en.js +38 -0
- package/data/examples/localization-i18n-en.tsx +60 -0
- package/data/examples/localization-i18n-es.js +38 -0
- package/data/examples/localization-i18n-es.tsx +60 -0
- package/data/examples/localization-i18n-et.js +38 -0
- package/data/examples/localization-i18n-et.tsx +60 -0
- package/data/examples/localization-i18n-fa.js +40 -0
- package/data/examples/localization-i18n-fa.tsx +66 -0
- package/data/examples/localization-i18n-fi.js +38 -0
- package/data/examples/localization-i18n-fi.tsx +60 -0
- package/data/examples/localization-i18n-fr.js +38 -0
- package/data/examples/localization-i18n-fr.tsx +60 -0
- package/data/examples/localization-i18n-he.js +40 -0
- package/data/examples/localization-i18n-he.tsx +66 -0
- package/data/examples/localization-i18n-hr.js +38 -0
- package/data/examples/localization-i18n-hr.tsx +60 -0
- package/data/examples/localization-i18n-hu.js +38 -0
- package/data/examples/localization-i18n-hu.tsx +60 -0
- package/data/examples/localization-i18n-hy.js +40 -0
- package/data/examples/localization-i18n-hy.tsx +65 -0
- package/data/examples/localization-i18n-id.js +38 -0
- package/data/examples/localization-i18n-id.tsx +60 -0
- package/data/examples/localization-i18n-it.js +38 -0
- package/data/examples/localization-i18n-it.tsx +60 -0
- package/data/examples/localization-i18n-ja.js +38 -0
- package/data/examples/localization-i18n-ja.tsx +60 -0
- package/data/examples/localization-i18n-ko.js +38 -0
- package/data/examples/localization-i18n-ko.tsx +60 -0
- package/data/examples/localization-i18n-nl.js +38 -0
- package/data/examples/localization-i18n-nl.tsx +60 -0
- package/data/examples/localization-i18n-no.js +38 -0
- package/data/examples/localization-i18n-no.tsx +60 -0
- package/data/examples/localization-i18n-np.js +38 -0
- package/data/examples/localization-i18n-np.tsx +60 -0
- package/data/examples/localization-i18n-pl.js +38 -0
- package/data/examples/localization-i18n-pl.tsx +60 -0
- package/data/examples/localization-i18n-pt-BR.js +38 -0
- package/data/examples/localization-i18n-pt-BR.tsx +60 -0
- package/data/examples/localization-i18n-pt.js +38 -0
- package/data/examples/localization-i18n-pt.tsx +60 -0
- package/data/examples/localization-i18n-ro.js +38 -0
- package/data/examples/localization-i18n-ro.tsx +60 -0
- package/data/examples/localization-i18n-ru.js +38 -0
- package/data/examples/localization-i18n-ru.tsx +60 -0
- package/data/examples/localization-i18n-sk.js +38 -0
- package/data/examples/localization-i18n-sk.tsx +60 -0
- package/data/examples/localization-i18n-sr-Cyrl-RS.js +38 -0
- package/data/examples/localization-i18n-sr-Cyrl-RS.tsx +60 -0
- package/data/examples/localization-i18n-sr-Latn-RS.js +38 -0
- package/data/examples/localization-i18n-sr-Latn-RS.tsx +60 -0
- package/data/examples/localization-i18n-sv.js +38 -0
- package/data/examples/localization-i18n-sv.tsx +60 -0
- package/data/examples/localization-i18n-tr.js +38 -0
- package/data/examples/localization-i18n-tr.tsx +60 -0
- package/data/examples/localization-i18n-uk.js +38 -0
- package/data/examples/localization-i18n-uk.tsx +60 -0
- package/data/examples/localization-i18n-vi.js +38 -0
- package/data/examples/localization-i18n-vi.tsx +60 -0
- package/data/examples/localization-i18n-zh-hans.js +38 -0
- package/data/examples/localization-i18n-zh-hans.tsx +60 -0
- package/data/examples/localization-i18n-zh-hant.js +38 -0
- package/data/examples/localization-i18n-zh-hant.tsx +60 -0
- package/data/examples/manual-selection.js +81 -0
- package/data/examples/manual-selection.tsx +105 -0
- package/data/examples/minimal.js +66 -0
- package/data/examples/minimal.tsx +78 -0
- package/data/examples/mui-theme.js +109 -0
- package/data/examples/mui-theme.tsx +136 -0
- package/data/examples/multi-sorting.js +48 -0
- package/data/examples/multi-sorting.tsx +58 -0
- package/data/examples/persistent-state.js +126 -0
- package/data/examples/persistent-state.tsx +184 -0
- package/data/examples/react-query.js +122 -0
- package/data/examples/react-query.tsx +182 -0
- package/data/examples/remote.js +113 -0
- package/data/examples/remote.tsx +150 -0
- package/data/examples/row-actions-buttons.js +54 -0
- package/data/examples/row-actions-buttons.tsx +89 -0
- package/data/examples/row-actions-menu-items.js +36 -0
- package/data/examples/row-actions-menu-items.tsx +64 -0
- package/data/examples/single-row-selection.js +74 -0
- package/data/examples/single-row-selection.tsx +98 -0
- package/data/examples/virtualized.js +122 -0
- package/data/examples/virtualized.tsx +138 -0
- package/data/guides/accessibility.md +119 -0
- package/data/guides/aggregation.md +210 -0
- package/data/guides/async-loading.md +132 -0
- package/data/guides/best-practices.md +363 -0
- package/data/guides/cell-actions.md +139 -0
- package/data/guides/click-to-copy.md +67 -0
- package/data/guides/column-actions.md +69 -0
- package/data/guides/column-filtering.md +366 -0
- package/data/guides/column-grouping.md +192 -0
- package/data/guides/column-hiding.md +133 -0
- package/data/guides/column-ordering-dnd.md +99 -0
- package/data/guides/column-pinning.md +72 -0
- package/data/guides/column-resizing.md +157 -0
- package/data/guides/column-size.md +162 -0
- package/data/guides/customize-components.md +395 -0
- package/data/guides/customize-icons.md +35 -0
- package/data/guides/data-columns.md +292 -0
- package/data/guides/density-toggle.md +46 -0
- package/data/guides/detail-panel.md +195 -0
- package/data/guides/display-columns.md +135 -0
- package/data/guides/editing.md +367 -0
- package/data/guides/expanding-sub-rows.md +194 -0
- package/data/guides/full-screen-toggle.md +63 -0
- package/data/guides/global-filtering.md +237 -0
- package/data/guides/localization.md +57 -0
- package/data/guides/memoization.md +157 -0
- package/data/guides/pagination.md +171 -0
- package/data/guides/row-actions.md +116 -0
- package/data/guides/row-numbers.md +24 -0
- package/data/guides/row-ordering-dnd.md +51 -0
- package/data/guides/row-pinning.md +96 -0
- package/data/guides/row-selection.md +237 -0
- package/data/guides/sorting.md +190 -0
- package/data/guides/state-management.md +165 -0
- package/data/guides/sticky-header.md +41 -0
- package/data/guides/table-event-listeners.md +103 -0
- package/data/guides/toolbar-customization.md +251 -0
- package/data/guides/virtualization.md +183 -0
- package/data/index.json +1930 -0
- package/data/reference/mrt-components.md +183 -0
- package/data/reference/mrt-hooks.md +125 -0
- package/data/skills/README.md +81 -0
- package/data/skills/composable-components/SKILL.md +189 -0
- package/data/skills/customization/SKILL.md +190 -0
- package/data/skills/drag-and-drop-ordering/SKILL.md +227 -0
- package/data/skills/editing/SKILL.md +243 -0
- package/data/skills/filtering/SKILL.md +213 -0
- package/data/skills/getting-started/SKILL.md +213 -0
- package/data/skills/localization/SKILL.md +182 -0
- package/data/skills/migrate-v3-to-v4/SKILL.md +161 -0
- package/data/skills/state-and-server-data/SKILL.md +200 -0
- package/data/skills/virtualization/SKILL.md +203 -0
- package/dist/data.js +159 -0
- package/dist/index.js +244 -0
- package/package.json +50 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { MaterialReactTable, useMaterialReactTable, createMRTColumnHelper, } from 'material-react-table';
|
|
2
|
+
import { Box, Button } from '@mui/material';
|
|
3
|
+
import FileDownloadIcon from '@mui/icons-material/FileDownload';
|
|
4
|
+
import { jsPDF } from 'jspdf'; //or use your library of choice here
|
|
5
|
+
import autoTable from 'jspdf-autotable';
|
|
6
|
+
import { data } from './makeData';
|
|
7
|
+
const columnHelper = createMRTColumnHelper();
|
|
8
|
+
const columns = [
|
|
9
|
+
columnHelper.accessor('id', {
|
|
10
|
+
header: 'ID',
|
|
11
|
+
size: 40,
|
|
12
|
+
}),
|
|
13
|
+
columnHelper.accessor('firstName', {
|
|
14
|
+
header: 'First Name',
|
|
15
|
+
size: 120,
|
|
16
|
+
}),
|
|
17
|
+
columnHelper.accessor('lastName', {
|
|
18
|
+
header: 'Last Name',
|
|
19
|
+
size: 120,
|
|
20
|
+
}),
|
|
21
|
+
columnHelper.accessor('company', {
|
|
22
|
+
header: 'Company',
|
|
23
|
+
size: 300,
|
|
24
|
+
}),
|
|
25
|
+
columnHelper.accessor('city', {
|
|
26
|
+
header: 'City',
|
|
27
|
+
}),
|
|
28
|
+
columnHelper.accessor('country', {
|
|
29
|
+
header: 'Country',
|
|
30
|
+
size: 220,
|
|
31
|
+
}),
|
|
32
|
+
];
|
|
33
|
+
const Example = () => {
|
|
34
|
+
const handleExportRows = (rows) => {
|
|
35
|
+
const doc = new jsPDF();
|
|
36
|
+
const tableData = rows.map((row) => Object.values(row.original));
|
|
37
|
+
const tableHeaders = columns.map((c) => c.header);
|
|
38
|
+
autoTable(doc, {
|
|
39
|
+
head: [tableHeaders],
|
|
40
|
+
body: tableData,
|
|
41
|
+
});
|
|
42
|
+
doc.save('mrt-pdf-example.pdf');
|
|
43
|
+
};
|
|
44
|
+
const table = useMaterialReactTable({
|
|
45
|
+
columns,
|
|
46
|
+
data,
|
|
47
|
+
enableRowSelection: true,
|
|
48
|
+
columnFilterDisplayMode: 'popover',
|
|
49
|
+
paginationDisplayMode: 'pages',
|
|
50
|
+
positionToolbarAlertBanner: 'bottom',
|
|
51
|
+
renderTopToolbarCustomActions: ({ table }) => (<Box sx={{
|
|
52
|
+
display: 'flex',
|
|
53
|
+
gap: '16px',
|
|
54
|
+
padding: '8px',
|
|
55
|
+
flexWrap: 'wrap',
|
|
56
|
+
}}>
|
|
57
|
+
<Button disabled={table.getPrePaginatedRowModel().rows.length === 0}
|
|
58
|
+
//export all rows, including from the next page, (still respects filtering and sorting)
|
|
59
|
+
onClick={() => handleExportRows(table.getPrePaginatedRowModel().rows)} startIcon={<FileDownloadIcon />}>
|
|
60
|
+
Export All Rows
|
|
61
|
+
</Button>
|
|
62
|
+
<Button disabled={table.getRowModel().rows.length === 0}
|
|
63
|
+
//export all rows as seen on the screen (respects pagination, sorting, filtering, etc.)
|
|
64
|
+
onClick={() => handleExportRows(table.getRowModel().rows)} startIcon={<FileDownloadIcon />}>
|
|
65
|
+
Export Page Rows
|
|
66
|
+
</Button>
|
|
67
|
+
<Button disabled={!table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()}
|
|
68
|
+
//only export selected rows
|
|
69
|
+
onClick={() => handleExportRows(table.getSelectedRowModel().rows)} startIcon={<FileDownloadIcon />}>
|
|
70
|
+
Export Selected Rows
|
|
71
|
+
</Button>
|
|
72
|
+
</Box>),
|
|
73
|
+
});
|
|
74
|
+
return <MaterialReactTable table={table}/>;
|
|
75
|
+
};
|
|
76
|
+
export default Example;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MaterialReactTable,
|
|
3
|
+
useMaterialReactTable,
|
|
4
|
+
type MRT_Row,
|
|
5
|
+
createMRTColumnHelper,
|
|
6
|
+
} from 'material-react-table';
|
|
7
|
+
import { Box, Button } from '@mui/material';
|
|
8
|
+
import FileDownloadIcon from '@mui/icons-material/FileDownload';
|
|
9
|
+
import { jsPDF } from 'jspdf'; //or use your library of choice here
|
|
10
|
+
import autoTable from 'jspdf-autotable';
|
|
11
|
+
import { data, type Person } from './makeData';
|
|
12
|
+
|
|
13
|
+
const columnHelper = createMRTColumnHelper<Person>();
|
|
14
|
+
|
|
15
|
+
const columns = [
|
|
16
|
+
columnHelper.accessor('id', {
|
|
17
|
+
header: 'ID',
|
|
18
|
+
size: 40,
|
|
19
|
+
}),
|
|
20
|
+
columnHelper.accessor('firstName', {
|
|
21
|
+
header: 'First Name',
|
|
22
|
+
size: 120,
|
|
23
|
+
}),
|
|
24
|
+
columnHelper.accessor('lastName', {
|
|
25
|
+
header: 'Last Name',
|
|
26
|
+
size: 120,
|
|
27
|
+
}),
|
|
28
|
+
columnHelper.accessor('company', {
|
|
29
|
+
header: 'Company',
|
|
30
|
+
size: 300,
|
|
31
|
+
}),
|
|
32
|
+
columnHelper.accessor('city', {
|
|
33
|
+
header: 'City',
|
|
34
|
+
}),
|
|
35
|
+
columnHelper.accessor('country', {
|
|
36
|
+
header: 'Country',
|
|
37
|
+
size: 220,
|
|
38
|
+
}),
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const Example = () => {
|
|
42
|
+
const handleExportRows = (rows: MRT_Row<Person>[]) => {
|
|
43
|
+
const doc = new jsPDF();
|
|
44
|
+
const tableData = rows.map((row) => Object.values(row.original));
|
|
45
|
+
const tableHeaders = columns.map((c) => c.header);
|
|
46
|
+
|
|
47
|
+
autoTable(doc, {
|
|
48
|
+
head: [tableHeaders],
|
|
49
|
+
body: tableData,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
doc.save('mrt-pdf-example.pdf');
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const table = useMaterialReactTable({
|
|
56
|
+
columns,
|
|
57
|
+
data,
|
|
58
|
+
enableRowSelection: true,
|
|
59
|
+
columnFilterDisplayMode: 'popover',
|
|
60
|
+
paginationDisplayMode: 'pages',
|
|
61
|
+
positionToolbarAlertBanner: 'bottom',
|
|
62
|
+
renderTopToolbarCustomActions: ({ table }) => (
|
|
63
|
+
<Box
|
|
64
|
+
sx={{
|
|
65
|
+
display: 'flex',
|
|
66
|
+
gap: '16px',
|
|
67
|
+
padding: '8px',
|
|
68
|
+
flexWrap: 'wrap',
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
<Button
|
|
72
|
+
disabled={table.getPrePaginatedRowModel().rows.length === 0}
|
|
73
|
+
//export all rows, including from the next page, (still respects filtering and sorting)
|
|
74
|
+
onClick={() => handleExportRows(table.getPrePaginatedRowModel().rows)}
|
|
75
|
+
startIcon={<FileDownloadIcon />}
|
|
76
|
+
>
|
|
77
|
+
Export All Rows
|
|
78
|
+
</Button>
|
|
79
|
+
<Button
|
|
80
|
+
disabled={table.getRowModel().rows.length === 0}
|
|
81
|
+
//export all rows as seen on the screen (respects pagination, sorting, filtering, etc.)
|
|
82
|
+
onClick={() => handleExportRows(table.getRowModel().rows)}
|
|
83
|
+
startIcon={<FileDownloadIcon />}
|
|
84
|
+
>
|
|
85
|
+
Export Page Rows
|
|
86
|
+
</Button>
|
|
87
|
+
<Button
|
|
88
|
+
disabled={
|
|
89
|
+
!table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()
|
|
90
|
+
}
|
|
91
|
+
//only export selected rows
|
|
92
|
+
onClick={() => handleExportRows(table.getSelectedRowModel().rows)}
|
|
93
|
+
startIcon={<FileDownloadIcon />}
|
|
94
|
+
>
|
|
95
|
+
Export Selected Rows
|
|
96
|
+
</Button>
|
|
97
|
+
</Box>
|
|
98
|
+
),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return <MaterialReactTable table={table} />;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default Example;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { MRT_GlobalFilterTextField, MRT_ShowHideColumnsButton, MRT_TablePagination, MRT_ToggleDensePaddingButton, MRT_ToggleFiltersButton, MRT_ToolbarAlertBanner, useMaterialReactTable, MRT_TableContainer, } from 'material-react-table';
|
|
2
|
+
import { IconButton, Box, Button, Typography, Tooltip } from '@mui/material';
|
|
3
|
+
import PrintIcon from '@mui/icons-material/Print';
|
|
4
|
+
import { data } from './makeData';
|
|
5
|
+
const columns = [
|
|
6
|
+
{
|
|
7
|
+
accessorKey: 'firstName',
|
|
8
|
+
header: 'First Name',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
accessorKey: 'lastName',
|
|
12
|
+
header: 'Last Name',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
accessorKey: 'age',
|
|
16
|
+
header: 'Age',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
accessorKey: 'salary',
|
|
20
|
+
header: 'Salary',
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
const Example = () => {
|
|
24
|
+
const table = useMaterialReactTable({
|
|
25
|
+
columns,
|
|
26
|
+
data,
|
|
27
|
+
enableRowSelection: true,
|
|
28
|
+
initialState: { showGlobalFilter: true },
|
|
29
|
+
});
|
|
30
|
+
return (<Box sx={{ border: 'gray 2px dashed', padding: '16px' }}>
|
|
31
|
+
{/* Our Custom External Top Toolbar */}
|
|
32
|
+
<Box sx={(theme) => ({
|
|
33
|
+
display: 'flex',
|
|
34
|
+
backgroundColor: 'inherit',
|
|
35
|
+
borderRadius: '4px',
|
|
36
|
+
flexDirection: 'row',
|
|
37
|
+
gap: '16px',
|
|
38
|
+
justifyContent: 'space-between',
|
|
39
|
+
padding: '24px 16px',
|
|
40
|
+
'@media max-width: 768px': {
|
|
41
|
+
flexDirection: 'column',
|
|
42
|
+
},
|
|
43
|
+
})}>
|
|
44
|
+
<Box>
|
|
45
|
+
<Button color="primary" onClick={() => {
|
|
46
|
+
alert('Add User');
|
|
47
|
+
}} variant="contained">
|
|
48
|
+
Create New Account
|
|
49
|
+
</Button>
|
|
50
|
+
</Box>
|
|
51
|
+
<MRT_GlobalFilterTextField table={table}/>
|
|
52
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
53
|
+
<MRT_ToggleFiltersButton table={table}/>
|
|
54
|
+
<MRT_ShowHideColumnsButton table={table}/>
|
|
55
|
+
<MRT_ToggleDensePaddingButton table={table}/>
|
|
56
|
+
<Tooltip title="Print">
|
|
57
|
+
<IconButton onClick={() => window.print()}>
|
|
58
|
+
<PrintIcon />
|
|
59
|
+
</IconButton>
|
|
60
|
+
</Tooltip>
|
|
61
|
+
</Box>
|
|
62
|
+
</Box>
|
|
63
|
+
{/* Some Page Content */}
|
|
64
|
+
<Typography sx={{
|
|
65
|
+
p: '16px 4px',
|
|
66
|
+
}}>
|
|
67
|
+
{"Hey I'm some page content. I'm just one of your normal components between your custom toolbar and the MRT Table below"}
|
|
68
|
+
</Typography>
|
|
69
|
+
{/* The MRT Table with no toolbars built-in */}
|
|
70
|
+
<MRT_TableContainer table={table}/>
|
|
71
|
+
{/* Our Custom Bottom Toolbar */}
|
|
72
|
+
<Box>
|
|
73
|
+
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
74
|
+
<MRT_TablePagination table={table}/>
|
|
75
|
+
</Box>
|
|
76
|
+
<Box sx={{ display: 'grid', width: '100%' }}>
|
|
77
|
+
<MRT_ToolbarAlertBanner stackAlertBanner table={table}/>
|
|
78
|
+
</Box>
|
|
79
|
+
</Box>
|
|
80
|
+
</Box>);
|
|
81
|
+
};
|
|
82
|
+
export default Example;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MRT_GlobalFilterTextField,
|
|
3
|
+
MRT_ShowHideColumnsButton,
|
|
4
|
+
MRT_TablePagination,
|
|
5
|
+
MRT_ToggleDensePaddingButton,
|
|
6
|
+
MRT_ToggleFiltersButton,
|
|
7
|
+
MRT_ToolbarAlertBanner,
|
|
8
|
+
useMaterialReactTable,
|
|
9
|
+
type MRT_ColumnDef,
|
|
10
|
+
MRT_TableContainer,
|
|
11
|
+
} from 'material-react-table';
|
|
12
|
+
import { IconButton, Box, Button, Typography, Tooltip } from '@mui/material';
|
|
13
|
+
import PrintIcon from '@mui/icons-material/Print';
|
|
14
|
+
import { data, type Person } from './makeData';
|
|
15
|
+
|
|
16
|
+
const columns: MRT_ColumnDef<Person>[] = [
|
|
17
|
+
{
|
|
18
|
+
accessorKey: 'firstName',
|
|
19
|
+
header: 'First Name',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
accessorKey: 'lastName',
|
|
23
|
+
header: 'Last Name',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
accessorKey: 'age',
|
|
27
|
+
header: 'Age',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
accessorKey: 'salary',
|
|
31
|
+
header: 'Salary',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const Example = () => {
|
|
36
|
+
const table = useMaterialReactTable({
|
|
37
|
+
columns,
|
|
38
|
+
data,
|
|
39
|
+
enableRowSelection: true,
|
|
40
|
+
initialState: { showGlobalFilter: true },
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Box sx={{ border: 'gray 2px dashed', padding: '16px' }}>
|
|
45
|
+
{/* Our Custom External Top Toolbar */}
|
|
46
|
+
<Box
|
|
47
|
+
sx={(theme) => ({
|
|
48
|
+
display: 'flex',
|
|
49
|
+
backgroundColor: 'inherit',
|
|
50
|
+
borderRadius: '4px',
|
|
51
|
+
flexDirection: 'row',
|
|
52
|
+
gap: '16px',
|
|
53
|
+
justifyContent: 'space-between',
|
|
54
|
+
padding: '24px 16px',
|
|
55
|
+
'@media max-width: 768px': {
|
|
56
|
+
flexDirection: 'column',
|
|
57
|
+
},
|
|
58
|
+
})}
|
|
59
|
+
>
|
|
60
|
+
<Box>
|
|
61
|
+
<Button
|
|
62
|
+
color="primary"
|
|
63
|
+
onClick={() => {
|
|
64
|
+
alert('Add User');
|
|
65
|
+
}}
|
|
66
|
+
variant="contained"
|
|
67
|
+
>
|
|
68
|
+
Create New Account
|
|
69
|
+
</Button>
|
|
70
|
+
</Box>
|
|
71
|
+
<MRT_GlobalFilterTextField table={table} />
|
|
72
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
|
73
|
+
<MRT_ToggleFiltersButton table={table} />
|
|
74
|
+
<MRT_ShowHideColumnsButton table={table} />
|
|
75
|
+
<MRT_ToggleDensePaddingButton table={table} />
|
|
76
|
+
<Tooltip title="Print">
|
|
77
|
+
<IconButton onClick={() => window.print()}>
|
|
78
|
+
<PrintIcon />
|
|
79
|
+
</IconButton>
|
|
80
|
+
</Tooltip>
|
|
81
|
+
</Box>
|
|
82
|
+
</Box>
|
|
83
|
+
{/* Some Page Content */}
|
|
84
|
+
<Typography
|
|
85
|
+
sx={{
|
|
86
|
+
p: '16px 4px',
|
|
87
|
+
}}
|
|
88
|
+
>
|
|
89
|
+
{
|
|
90
|
+
"Hey I'm some page content. I'm just one of your normal components between your custom toolbar and the MRT Table below"
|
|
91
|
+
}
|
|
92
|
+
</Typography>
|
|
93
|
+
{/* The MRT Table with no toolbars built-in */}
|
|
94
|
+
<MRT_TableContainer table={table} />
|
|
95
|
+
{/* Our Custom Bottom Toolbar */}
|
|
96
|
+
<Box>
|
|
97
|
+
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
|
98
|
+
<MRT_TablePagination table={table} />
|
|
99
|
+
</Box>
|
|
100
|
+
<Box sx={{ display: 'grid', width: '100%' }}>
|
|
101
|
+
<MRT_ToolbarAlertBanner stackAlertBanner table={table} />
|
|
102
|
+
</Box>
|
|
103
|
+
</Box>
|
|
104
|
+
</Box>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default Example;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { MaterialReactTable, } from 'material-react-table';
|
|
3
|
+
import { data } from './makeData';
|
|
4
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
5
|
+
import { faArrowDownWideShort, faBars, faBarsStaggered, faColumns, faCompress, faEllipsisH, faEllipsisVertical, faExpand, faEyeSlash, faFilter, faFilterCircleXmark, faGripLines, faSearch, faSearchMinus, faSortDown, faThumbTack, } from '@fortawesome/free-solid-svg-icons';
|
|
6
|
+
import '@fortawesome/fontawesome-svg-core/styles.css';
|
|
7
|
+
import { config } from '@fortawesome/fontawesome-svg-core';
|
|
8
|
+
config.autoAddCss = false;
|
|
9
|
+
/**
|
|
10
|
+
* These are just some of the icons visible in this table's feature set.
|
|
11
|
+
* If you skip customizing some icons, those particular icons will fallback the the default Material UI icons.
|
|
12
|
+
*/
|
|
13
|
+
const fontAwesomeIcons = {
|
|
14
|
+
ArrowDownwardIcon: (props) => (<FontAwesomeIcon icon={faSortDown} {...props}/>),
|
|
15
|
+
ClearAllIcon: () => <FontAwesomeIcon icon={faBarsStaggered}/>,
|
|
16
|
+
DensityLargeIcon: () => <FontAwesomeIcon icon={faGripLines}/>,
|
|
17
|
+
DensityMediumIcon: () => <FontAwesomeIcon icon={faBars}/>,
|
|
18
|
+
DensitySmallIcon: () => <FontAwesomeIcon icon={faBars}/>,
|
|
19
|
+
DragHandleIcon: () => <FontAwesomeIcon icon={faGripLines}/>,
|
|
20
|
+
FilterListIcon: (props) => (<FontAwesomeIcon icon={faFilter} {...props}/>),
|
|
21
|
+
FilterListOffIcon: () => <FontAwesomeIcon icon={faFilterCircleXmark}/>,
|
|
22
|
+
FullscreenExitIcon: () => <FontAwesomeIcon icon={faCompress}/>,
|
|
23
|
+
FullscreenIcon: () => <FontAwesomeIcon icon={faExpand}/>,
|
|
24
|
+
SearchIcon: (props) => <FontAwesomeIcon icon={faSearch} {...props}/>,
|
|
25
|
+
SearchOffIcon: () => <FontAwesomeIcon icon={faSearchMinus}/>,
|
|
26
|
+
ViewColumnIcon: () => <FontAwesomeIcon icon={faColumns}/>,
|
|
27
|
+
MoreVertIcon: () => <FontAwesomeIcon icon={faEllipsisVertical}/>,
|
|
28
|
+
MoreHorizIcon: () => <FontAwesomeIcon icon={faEllipsisH}/>,
|
|
29
|
+
SortIcon: (props) => (<FontAwesomeIcon icon={faArrowDownWideShort} {...props}/> //props so that style rotation transforms are applied
|
|
30
|
+
),
|
|
31
|
+
PushPinIcon: (props) => (<FontAwesomeIcon icon={faThumbTack} {...props}/> //props so that style rotation transforms are applied
|
|
32
|
+
),
|
|
33
|
+
VisibilityOffIcon: () => <FontAwesomeIcon icon={faEyeSlash}/>,
|
|
34
|
+
};
|
|
35
|
+
const Example = () => {
|
|
36
|
+
const columns = useMemo(
|
|
37
|
+
//column definitions...
|
|
38
|
+
() => [
|
|
39
|
+
{
|
|
40
|
+
accessorKey: 'firstName',
|
|
41
|
+
header: 'First Name',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
accessorKey: 'lastName',
|
|
45
|
+
header: 'Last Name',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
accessorKey: 'address',
|
|
49
|
+
header: 'Address',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
accessorKey: 'city',
|
|
53
|
+
header: 'City',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
accessorKey: 'state',
|
|
57
|
+
header: 'State',
|
|
58
|
+
},
|
|
59
|
+
], []);
|
|
60
|
+
return (<MaterialReactTable columns={columns} data={data} enableColumnOrdering enableColumnPinning icons={fontAwesomeIcons}/>);
|
|
61
|
+
};
|
|
62
|
+
export default Example;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
MaterialReactTable,
|
|
4
|
+
type MRT_ColumnDef,
|
|
5
|
+
type MRT_Icons,
|
|
6
|
+
} from 'material-react-table';
|
|
7
|
+
import { data, type Person } from './makeData';
|
|
8
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
9
|
+
import {
|
|
10
|
+
faArrowDownWideShort,
|
|
11
|
+
faBars,
|
|
12
|
+
faBarsStaggered,
|
|
13
|
+
faColumns,
|
|
14
|
+
faCompress,
|
|
15
|
+
faEllipsisH,
|
|
16
|
+
faEllipsisVertical,
|
|
17
|
+
faExpand,
|
|
18
|
+
faEyeSlash,
|
|
19
|
+
faFilter,
|
|
20
|
+
faFilterCircleXmark,
|
|
21
|
+
faGripLines,
|
|
22
|
+
faSearch,
|
|
23
|
+
faSearchMinus,
|
|
24
|
+
faSortDown,
|
|
25
|
+
faThumbTack,
|
|
26
|
+
} from '@fortawesome/free-solid-svg-icons';
|
|
27
|
+
import '@fortawesome/fontawesome-svg-core/styles.css';
|
|
28
|
+
import { config } from '@fortawesome/fontawesome-svg-core';
|
|
29
|
+
config.autoAddCss = false;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* These are just some of the icons visible in this table's feature set.
|
|
33
|
+
* If you skip customizing some icons, those particular icons will fallback the the default Material UI icons.
|
|
34
|
+
*/
|
|
35
|
+
const fontAwesomeIcons: Partial<MRT_Icons> = {
|
|
36
|
+
ArrowDownwardIcon: (props: any) => (
|
|
37
|
+
<FontAwesomeIcon icon={faSortDown} {...props} />
|
|
38
|
+
),
|
|
39
|
+
ClearAllIcon: () => <FontAwesomeIcon icon={faBarsStaggered} />,
|
|
40
|
+
DensityLargeIcon: () => <FontAwesomeIcon icon={faGripLines} />,
|
|
41
|
+
DensityMediumIcon: () => <FontAwesomeIcon icon={faBars} />,
|
|
42
|
+
DensitySmallIcon: () => <FontAwesomeIcon icon={faBars} />,
|
|
43
|
+
DragHandleIcon: () => <FontAwesomeIcon icon={faGripLines} />,
|
|
44
|
+
FilterListIcon: (props: any) => (
|
|
45
|
+
<FontAwesomeIcon icon={faFilter} {...props} />
|
|
46
|
+
),
|
|
47
|
+
FilterListOffIcon: () => <FontAwesomeIcon icon={faFilterCircleXmark} />,
|
|
48
|
+
FullscreenExitIcon: () => <FontAwesomeIcon icon={faCompress} />,
|
|
49
|
+
FullscreenIcon: () => <FontAwesomeIcon icon={faExpand} />,
|
|
50
|
+
SearchIcon: (props: any) => <FontAwesomeIcon icon={faSearch} {...props} />,
|
|
51
|
+
SearchOffIcon: () => <FontAwesomeIcon icon={faSearchMinus} />,
|
|
52
|
+
ViewColumnIcon: () => <FontAwesomeIcon icon={faColumns} />,
|
|
53
|
+
MoreVertIcon: () => <FontAwesomeIcon icon={faEllipsisVertical} />,
|
|
54
|
+
MoreHorizIcon: () => <FontAwesomeIcon icon={faEllipsisH} />,
|
|
55
|
+
SortIcon: (props: any) => (
|
|
56
|
+
<FontAwesomeIcon icon={faArrowDownWideShort} {...props} /> //props so that style rotation transforms are applied
|
|
57
|
+
),
|
|
58
|
+
PushPinIcon: (props: any) => (
|
|
59
|
+
<FontAwesomeIcon icon={faThumbTack} {...props} /> //props so that style rotation transforms are applied
|
|
60
|
+
),
|
|
61
|
+
VisibilityOffIcon: () => <FontAwesomeIcon icon={faEyeSlash} />,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const Example = () => {
|
|
65
|
+
const columns = useMemo(
|
|
66
|
+
//column definitions...
|
|
67
|
+
() =>
|
|
68
|
+
[
|
|
69
|
+
{
|
|
70
|
+
accessorKey: 'firstName',
|
|
71
|
+
header: 'First Name',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
accessorKey: 'lastName',
|
|
75
|
+
header: 'Last Name',
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
{
|
|
79
|
+
accessorKey: 'address',
|
|
80
|
+
header: 'Address',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
accessorKey: 'city',
|
|
84
|
+
header: 'City',
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
{
|
|
88
|
+
accessorKey: 'state',
|
|
89
|
+
header: 'State',
|
|
90
|
+
},
|
|
91
|
+
] as MRT_ColumnDef<Person>[],
|
|
92
|
+
[], //end
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<MaterialReactTable
|
|
97
|
+
columns={columns}
|
|
98
|
+
data={data}
|
|
99
|
+
enableColumnOrdering
|
|
100
|
+
enableColumnPinning
|
|
101
|
+
icons={fontAwesomeIcons}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default Example;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState, } from 'react';
|
|
2
|
+
import { MaterialReactTable, useMaterialReactTable, } from 'material-react-table';
|
|
3
|
+
import { Typography } from '@mui/material';
|
|
4
|
+
import { QueryClient, QueryClientProvider, useInfiniteQuery, } from '@tanstack/react-query'; //Note: this is TanStack React Query V5
|
|
5
|
+
const columns = [
|
|
6
|
+
{
|
|
7
|
+
accessorKey: 'firstName',
|
|
8
|
+
header: 'First Name',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
accessorKey: 'lastName',
|
|
12
|
+
header: 'Last Name',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
accessorKey: 'address',
|
|
16
|
+
header: 'Address',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
accessorKey: 'state',
|
|
20
|
+
header: 'State',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
accessorKey: 'phoneNumber',
|
|
24
|
+
header: 'Phone Number',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
const fetchSize = 25;
|
|
28
|
+
const Example = () => {
|
|
29
|
+
const tableContainerRef = useRef(null); //we can get access to the underlying TableContainer element and react to its scroll events
|
|
30
|
+
const rowVirtualizerInstanceRef = useRef(null); //we can get access to the underlying Virtualizer instance and call its scrollToIndex method
|
|
31
|
+
const [columnFilters, setColumnFilters] = useState([]);
|
|
32
|
+
const [globalFilter, setGlobalFilter] = useState();
|
|
33
|
+
const [sorting, setSorting] = useState([]);
|
|
34
|
+
const { data, fetchNextPage, isError, isFetching, isLoading } = useInfiniteQuery({
|
|
35
|
+
queryKey: [
|
|
36
|
+
'users-list',
|
|
37
|
+
{
|
|
38
|
+
columnFilters, //refetch when columnFilters changes
|
|
39
|
+
globalFilter, //refetch when globalFilter changes
|
|
40
|
+
sorting, //refetch when sorting changes
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
queryFn: async ({ pageParam }) => {
|
|
44
|
+
const url = new URL('/api/data', location.origin); // nextjs api route
|
|
45
|
+
url.searchParams.set('start', `${pageParam * fetchSize}`);
|
|
46
|
+
url.searchParams.set('size', `${fetchSize}`);
|
|
47
|
+
url.searchParams.set('filters', JSON.stringify(columnFilters ?? []));
|
|
48
|
+
url.searchParams.set('globalFilter', globalFilter ?? '');
|
|
49
|
+
url.searchParams.set('sorting', JSON.stringify(sorting ?? []));
|
|
50
|
+
const response = await fetch(url.href);
|
|
51
|
+
const json = (await response.json());
|
|
52
|
+
return json;
|
|
53
|
+
},
|
|
54
|
+
initialPageParam: 0,
|
|
55
|
+
getNextPageParam: (_lastGroup, groups) => groups.length,
|
|
56
|
+
refetchOnWindowFocus: false,
|
|
57
|
+
});
|
|
58
|
+
const flatData = useMemo(() => data?.pages.flatMap((page) => page.data) ?? [], [data]);
|
|
59
|
+
const totalDBRowCount = data?.pages?.[0]?.meta?.totalRowCount ?? 0;
|
|
60
|
+
const totalFetched = flatData.length;
|
|
61
|
+
//called on scroll and possibly on mount to fetch more data as the user scrolls and reaches bottom of table
|
|
62
|
+
const fetchMoreOnBottomReached = useCallback((containerRefElement) => {
|
|
63
|
+
if (containerRefElement) {
|
|
64
|
+
const { scrollHeight, scrollTop, clientHeight } = containerRefElement;
|
|
65
|
+
//once the user has scrolled within 400px of the bottom of the table, fetch more data if we can
|
|
66
|
+
if (scrollHeight - scrollTop - clientHeight < 400 &&
|
|
67
|
+
!isFetching &&
|
|
68
|
+
totalFetched < totalDBRowCount) {
|
|
69
|
+
fetchNextPage();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, [fetchNextPage, isFetching, totalFetched, totalDBRowCount]);
|
|
73
|
+
//scroll to top of table when sorting or filters change
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
//scroll to the top of the table when the sorting changes
|
|
76
|
+
try {
|
|
77
|
+
rowVirtualizerInstanceRef.current?.scrollToIndex?.(0);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error(error);
|
|
81
|
+
}
|
|
82
|
+
}, [sorting, columnFilters, globalFilter]);
|
|
83
|
+
//a check on mount to see if the table is already scrolled to the bottom and immediately needs to fetch more data
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
fetchMoreOnBottomReached(tableContainerRef.current);
|
|
86
|
+
}, [fetchMoreOnBottomReached]);
|
|
87
|
+
const table = useMaterialReactTable({
|
|
88
|
+
columns,
|
|
89
|
+
data: flatData,
|
|
90
|
+
enablePagination: false,
|
|
91
|
+
enableRowNumbers: true,
|
|
92
|
+
enableRowVirtualization: true,
|
|
93
|
+
manualFiltering: true,
|
|
94
|
+
manualSorting: true,
|
|
95
|
+
muiTableContainerProps: {
|
|
96
|
+
ref: tableContainerRef, //get access to the table container element
|
|
97
|
+
sx: { maxHeight: '600px' }, //give the table a max height
|
|
98
|
+
onScroll: (event) => fetchMoreOnBottomReached(event.target), //add an event listener to the table container element
|
|
99
|
+
},
|
|
100
|
+
muiToolbarAlertBannerProps: isError
|
|
101
|
+
? {
|
|
102
|
+
color: 'error',
|
|
103
|
+
children: 'Error loading data',
|
|
104
|
+
}
|
|
105
|
+
: undefined,
|
|
106
|
+
onColumnFiltersChange: setColumnFilters,
|
|
107
|
+
onGlobalFilterChange: setGlobalFilter,
|
|
108
|
+
onSortingChange: setSorting,
|
|
109
|
+
renderBottomToolbarCustomActions: () => (<Typography>
|
|
110
|
+
Fetched {totalFetched} of {totalDBRowCount} total rows.
|
|
111
|
+
</Typography>),
|
|
112
|
+
state: {
|
|
113
|
+
columnFilters,
|
|
114
|
+
globalFilter,
|
|
115
|
+
isLoading,
|
|
116
|
+
showAlertBanner: isError,
|
|
117
|
+
showProgressBars: isFetching,
|
|
118
|
+
sorting,
|
|
119
|
+
},
|
|
120
|
+
rowVirtualizerInstanceRef, //get access to the virtualizer instance
|
|
121
|
+
rowVirtualizerOptions: { overscan: 4 },
|
|
122
|
+
});
|
|
123
|
+
return <MaterialReactTable table={table}/>;
|
|
124
|
+
};
|
|
125
|
+
//react query setup in App.tsx
|
|
126
|
+
const ReactQueryDevtoolsProduction = lazy(() => import('@tanstack/react-query-devtools/build/modern/production.js').then((d) => ({
|
|
127
|
+
default: d.ReactQueryDevtools,
|
|
128
|
+
})));
|
|
129
|
+
const queryClient = new QueryClient();
|
|
130
|
+
export default function App() {
|
|
131
|
+
return (<QueryClientProvider client={queryClient}>
|
|
132
|
+
<Example />
|
|
133
|
+
<Suspense fallback={null}>
|
|
134
|
+
<ReactQueryDevtoolsProduction />
|
|
135
|
+
</Suspense>
|
|
136
|
+
</QueryClientProvider>);
|
|
137
|
+
}
|