Advanced Example
Here is a more advanced example showcasing Material React Table's many features. Features such as row selection, expanding detail panels, header groups, column ordering, column pinning, column grouping, custom column and cell renders, etc., can be seen here.
This example is still only using client-side features. If you want to see an example of how to use Material React Table with server side logic and remote data, check out either the Remote Data Example or the React-Query Example.
Employee | Job Info | ||||||
---|---|---|---|---|---|---|---|
Actions | Name | Email | Salary | Job Title | Start Date Filter Mode: Lesss Than | ||
![]() Dusty Kuvalis | $52,729 | Chief Creative Technician | 3/20/2014 | ||||
![]() D'angelo Moen | $71,964 | Forward Response Engineer | 3/9/2018 | ||||
![]() Devan Reinger | $72,551 | Customer Intranet Consultant | 8/12/2020 | ||||
![]() Leonardo Langworth | $57,801 | Senior Security Manager | 7/25/2017 | ||||
![]() Douglas Denesik | $23,792 | Legacy Security Assistant | 4/12/2020 | ||||
![]() Jameson Mayer | $80,916 | Regional Division Planner | 10/30/2017 | ||||
![]() Madaline Quitzon | $68,052 | Corporate Paradigm Strategist | 1/17/2018 | ||||
![]() Wilfrid Vandervort | $85,573 | Legacy Functionality Specialist | 8/4/2014 | ||||
![]() Chelsie Mraz | $51,062 | Forward Infrastructure Representative | 1/6/2021 | ||||
![]() Hassie Bruen | $61,196 | Human Paradigm Designer | 4/28/2016 | ||||
1import React, { useMemo } from 'react';23//MRT Imports4import MaterialReactTable from 'material-react-table';56//Material-UI Imports7import {8 Box,9 Button,10 ListItemIcon,11 MenuItem,12 Typography,13 TextField,14} from '@mui/material';1516//Date Picker Imports17import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';18import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';19import { DatePicker } from '@mui/x-date-pickers/DatePicker';2021//Icons Imports22import { AccountCircle, Send } from '@mui/icons-material';2324//Mock Data25import { data } from './makeData';2627const Example = () => {28 const columns = useMemo(29 () => [30 {31 id: 'employee', //id used to define `group` column32 header: 'Employee',33 columns: [34 {35 accessorFn: (row) => `${row.firstName} ${row.lastName}`, //accessorFn used to join multiple data into a single cell36 id: 'name', //id is still required when using accessorFn instead of accessorKey37 header: 'Name',38 size: 250,39 Cell: ({ cell, row }) => (40 <Box41 sx={{42 display: 'flex',43 alignItems: 'center',44 gap: '1rem',45 }}46 >47 <img48 alt="avatar"49 height={30}50 src={row.original.avatar}51 loading="lazy"52 style={{ borderRadius: '50%' }}53 />54 <Typography>{cell.getValue()}</Typography>55 </Box>56 ),57 },58 {59 accessorKey: 'email', //accessorKey used to define `data` column. `id` gets set to accessorKey automatically60 enableClickToCopy: true,61 header: 'Email',62 size: 300,63 },64 ],65 },66 {67 id: 'id',68 header: 'Job Info',69 columns: [70 {71 accessorKey: 'salary',72 filterVariant: 'range',73 header: 'Salary',74 size: 200,75 //custom conditional format and styling76 Cell: ({ cell }) => (77 <Box78 sx={(theme) => ({79 backgroundColor:80 cell.getValue() < 50_00081 ? theme.palette.error.dark82 : cell.getValue() >= 50_000 && cell.getValue() < 75_00083 ? theme.palette.warning.dark84 : theme.palette.success.dark,85 borderRadius: '0.25rem',86 color: '#fff',87 maxWidth: '9ch',88 p: '0.25rem',89 })}90 >91 {cell.getValue()?.toLocaleString?.('en-US', {92 style: 'currency',93 currency: 'USD',94 minimumFractionDigits: 0,95 maximumFractionDigits: 0,96 })}97 </Box>98 ),99 },100 {101 accessorKey: 'jobTitle', //hey a simple column for once102 header: 'Job Title',103 size: 350,104 },105 {106 accessorFn: (row) => new Date(row.startDate), //convert to Date for sorting and filtering107 id: 'startDate',108 header: 'Start Date',109 filterFn: 'lessThanOrEqualTo',110 sortingFn: 'datetime',111 Cell: ({ cell }) => cell.getValue()?.toLocaleDateString(), //render Date as a string112 Header: ({ column }) => <em>{column.columnDef.header}</em>, //custom header markup113 //Custom Date Picker Filter from @mui/x-date-pickers114 Filter: ({ column }) => (115 <LocalizationProvider dateAdapter={AdapterDayjs}>116 <DatePicker117 onChange={(newValue) => {118 column.setFilterValue(newValue);119 }}120 renderInput={(params) => (121 <TextField122 {...params}123 helperText={'Filter Mode: Lesss Than'}124 sx={{ minWidth: '120px' }}125 variant="standard"126 />127 )}128 value={column.getFilterValue()}129 />130 </LocalizationProvider>131 ),132 },133 ],134 },135 ],136 [],137 );138139 return (140 <MaterialReactTable141 columns={columns}142 data={data}143 enableColumnFilterModes144 enableColumnOrdering145 enableGrouping146 enablePinning147 enableRowActions148 enableRowSelection149 initialState={{ showColumnFilters: true }}150 positionToolbarAlertBanner="bottom"151 renderDetailPanel={({ row }) => (152 <Box153 sx={{154 display: 'flex',155 justifyContent: 'space-around',156 alignItems: 'center',157 }}158 >159 <img160 alt="avatar"161 height={200}162 src={row.original.avatar}163 loading="lazy"164 style={{ borderRadius: '50%' }}165 />166 <Box sx={{ textAlign: 'center' }}>167 <Typography variant="h4">Signature Catch Phrase:</Typography>168 <Typography variant="h1">169 "{row.original.signatureCatchPhrase}"170 </Typography>171 </Box>172 </Box>173 )}174 renderRowActionMenuItems={({ closeMenu }) => [175 <MenuItem176 key={0}177 onClick={() => {178 // View profile logic...179 closeMenu();180 }}181 sx={{ m: 0 }}182 >183 <ListItemIcon>184 <AccountCircle />185 </ListItemIcon>186 View Profile187 </MenuItem>,188 <MenuItem189 key={1}190 onClick={() => {191 // Send email logic...192 closeMenu();193 }}194 sx={{ m: 0 }}195 >196 <ListItemIcon>197 <Send />198 </ListItemIcon>199 Send Email200 </MenuItem>,201 ]}202 renderTopToolbarCustomActions={({ table }) => {203 const handleDeactivate = () => {204 table.getSelectedRowModel().flatRows.map((row) => {205 alert('deactivating ' + row.getValue('name'));206 });207 };208209 const handleActivate = () => {210 table.getSelectedRowModel().flatRows.map((row) => {211 alert('activating ' + row.getValue('name'));212 });213 };214215 const handleContact = () => {216 table.getSelectedRowModel().flatRows.map((row) => {217 alert('contact ' + row.getValue('name'));218 });219 };220221 return (222 <div style={{ display: 'flex', gap: '0.5rem' }}>223 <Button224 color="error"225 disabled={table.getSelectedRowModel().flatRows.length === 0}226 onClick={handleDeactivate}227 variant="contained"228 >229 Deactivate230 </Button>231 <Button232 color="success"233 disabled={table.getSelectedRowModel().flatRows.length === 0}234 onClick={handleActivate}235 variant="contained"236 >237 Activate238 </Button>239 <Button240 color="info"241 disabled={table.getSelectedRowModel().flatRows.length === 0}242 onClick={handleContact}243 variant="contained"244 >245 Contact246 </Button>247 </div>248 );249 }}250 />251 );252};253254export default Example;255
View Extra Storybook Examples