DataGrid
Data grids are used to organize lists of high density data.
A advanced data grid component that supports sorting, selections, filters and pagination.
- Beta
Buy Pro
- 0.40.0 (latest)
Import#
import {DataGrid,DataGridPagination,useColumns,useColumnVisibility,} from '@saas-ui-pro/react'
Usage#
DataGrid uses @tanstack/react-table
v8 internally, and supports all useTable
props, you can find the docs here.
Basic DataGrid#
import { Button } from '@chakra-ui/react'import {Page,PageHeader,DataGrid,DataGridPagination,} from '@saas-ui-pro/react'export default function ListPage() {const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},{id: 'action',disableSortBy: true,disableGlobaFilter: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),size: 100,},]}, [])return (<Page height="400px"><PageHeader title="Customers" /><PageBody p="0" contentWidth="full"><DataGridcolumns={columns}data={dataTable.data}isSortableisSelectableisHoverable><DataGridPagination /></DataGrid></PageBody></Page>)}
Sticky header#
Sticky headers are enabled by default, but can be disabled by passing stickyHeader={false}
to DataGrid
.
Use style props to customize the header styles.
import { Button, Card } from '@chakra-ui/react'import { DataGrid, DataGridPagination } from '@saas-ui-pro/react'export default function ListPage() {const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},{id: 'action',disableSortBy: true,disableGlobaFilter: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),size: 100,},]}, [])return (<Card overflow="hidden"><DataGridcolumns={columns}data={dataTable.data}stickyHeader={false}sx={{'& thead': {bg: 'gray.50',_dark: {bg: 'gray.900',},},}}><DataGridPagination /></DataGrid></Card>)}
Column resizing#
Column resizing is disabled by default, but can be enabled by passing columnResizeEnabled
to DataGrid
.
import { Button, Card } from '@chakra-ui/react'import { DataGrid, DataGridPagination } from '@saas-ui-pro/react'export default function ListPage() {const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},{id: 'action',disableSortBy: true,disableGlobaFilter: true,disableResizing: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),size: 100,},]}, [])return (<Card overflow="hidden"><DataGrid columns={columns} data={dataTable.data} columnResizeEnabled><DataGridPagination /></DataGrid></Card>)}
Pinned columns#
Pinned columns are columns that are always visible when scrolling horizontally.
DataGrid
supports both left and right pinned columns.
To pin a column, use the columnPinning
prop in intialState
or state
props.
Setting it in state
prop will allow you to change the pinned columns dynamically using React state.
import { Button, Card } from '@chakra-ui/react'import { DataGrid, DataGridPagination } from '@saas-ui-pro/react'export default function ListPage() {const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},{id: 'action',disableSortBy: true,disableGlobaFilter: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),size: 100,},]}, [])return (<Card overflow="hidden"><DataGridcolumns={columns}data={dataTable.data}initialState={{columnPinning: {left: ['selection', 'name'],right: ['action'],},}}><DataGridPagination /></DataGrid></Card>)}
With BulkActions#
import { Button } from '@chakra-ui/react'import {Page,PageHeader,DataGrid,DataGridPagination,BulkActions,} from '@saas-ui-pro/react'export default function ListPage() {const [selections, setSelections] = React.useState([])const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',isNumeric: true,},{id: 'action',disableSortBy: true,disableGlobaFilter: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),size: 100,},]}, [])return (<Page height="400px"><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><BulkActions selections={selections} maxW="400px"><Button colorScheme="white">Delete</Button></BulkActions><DataGridcolumns={columns}data={dataTable.data}isSortableisSelectableisHoverablerowVirtualizer={{ enabled: false }}onSelectedRowsChange={setSelections}initialState={{rowSelection: { 1: true },}}><DataGridPagination /></DataGrid></PageBody></Page>)}
Clickable rows#
Cells with a href
property will render the cell value in an a
.
Using the DataGrid onRowClick
handler you can trigger a click event on the link whenever the row is clicked.
import { Button } from '@chakra-ui/react'import {Page,PageHeader,DataGrid,DataGridPagination,BulkActions,} from '@saas-ui-pro/react'export default function ListPage() {const [selections, setSelections] = React.useState([])const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,meta: {href: ({ id }) => `#customers/${id}`,},},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},{id: 'action',disableSortBy: true,disableGlobaFilter: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),size: 200,},]}, [])return (<Pageheight="400px"sx={{'& tbody tr:hover': {cursor: 'pointer',},}}><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><BulkActions selections={selections} width="400px"><Button colorScheme="white">Delete</Button></BulkActions><DataGridcolumns={columns}data={dataTable.data}isSortableisSelectableisHoverableonSelectedRowsChange={setSelections}onRowClick={(row, e) => {// Find the first A and trigger a click.const link = e.currentTarget.querySelector('td a')link && link.click()}}><DataGridPagination /></DataGrid></PageBody></Page>)}
Nested rows#
Use the isExpandable
prop to enable row expanding. The default property for nested rows is subRows
.
To use a custom property for nested rows, use the getSubRows
prop.
For more than one level of nesting, it's recommended to use tableLayout=auto
on the DataGrid
component.
import { Button } from '@chakra-ui/react'import { Page, PageHeader, DataGrid } from '@saas-ui-pro/react'const demoData = dataTable.data.map((row, i) => {return {...row,subRows: [{id: row.id + '-1',...row,},{id: row.id + '-2',...row,},],}})export default function ListPage() {const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,meta: {href: ({ id }) => `#customers/${id}`,},},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},]}, [])return (<Page height="400px"><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><DataGrid columns={columns} data={demoData} isSortable isExpandable /></PageBody></Page>)}
Remote data#
By default all sorting, filtering and pagination is handled locally by react-table
to work with remote data use this example as a reference.
This example uses React Query to fetch data.
import { Button } from '@chakra-ui/react'import {Page,PageHeader,DataGrid,DataGridPagination,SortingState,BulkActions,} from '@saas-ui-pro/react'// import { useQuery } from '@tanstack/react-query'export default function ListPage() {const [selections, setSelections] = React.useState([])const [sort, setSort] = React.useState < SortingState > []const [page, setPage] = React.useState(0)const { data } = useQuery(['customers', sort, page], () => {// fetch...})const columns = React.useMemo(() => {return [{accessorKey: 'name',header: 'Name',size: 200,meta: {href: ({ id }) => `#customers/${id}`,},},{accessorKey: 'email',header: 'Email',},{accessorKey: 'company',header: 'Company',},{accessorKey: 'country',header: 'Country',},{accessorKey: 'employees',header: 'Employees',meta: {isNumeric: true,},},{id: 'action',disableSortBy: true,disableGlobaFilter: true,header: '',cell: () => (<><Button size="xs">Edit</Button></>),width: '100px',},]}, [])return (<Pageheight="400px"sx={{'& tbody tr:hover': {cursor: 'pointer',},}}><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><BulkActions selections={selections}><Button colorScheme="white" variant="subtle">Delete</Button></BulkActions><DataGridcolumns={columns}data={dataTable.data}isSortableisSelectableisHoverableonSelectedRowsChange={setSelections}onRowClick={(row, e) => {// Find the first A and trigger a click.const link = e.currentTarget.querySelector('td a')link && link.click()}}manualSortByonSortChange={setSort}pageCount={data.total}initialState={{pagination: {pageSize: 1,},}}state={{sorting: { sort },}}><DataGridPaginationonChange={({ pageIndex }) => setPage(pageIndex)}/></DataGrid></PageBody></Page>)}
Access internal state#
You can access the react-table TableInstance
by passing a ref to DataGrid
.
Check out the react-table documentation for all properties.
import {Page,PageHeader,PageBody,Toolbar,ToolbarButton,DataGrid,} from '@saas-ui-pro/react'export default function InternalState() {const gridRef = useRef(null)return (<Page title="Customers" height="400px"><PageHeadertitle="Customers"toolbar={<Toolbar><ToolbarButtononClick={() => {gridRef.current.toggleAllRowsSelected()}}label="Select all rows"variant="primary"/></Toolbar>}/><PageBody p="0" contentWidth="full" position="relative"><DataGridinstanceRef={gridRef}columns={dataGrid.columns.concat()}data={dataGrid.data.concat()}isSelectable/></PageBody></Page>)}
Toggle visible columns#
import {Menu,MenuButton,MenuList,MenuOptionGroup,MenuOptionItem,Button,} from '@chakra-ui/react'import {Page,PageHeader,PageBody,Toolbar,DataGrid,useColumnVisibility,} from '@saas-ui-pro/react'export default function VisibleColumns() {const allColumns = ['name', 'email', 'company', 'country', 'employees']const [visibleColumns, setVisibleColumns] = React.useState(['name','email','company',])const columnVisibility = useColumnVisibility({columns: dataGrid.columns,visibleColumns,})return (<Page title="Customers" height="400px"><PageHeadertitle="Customers"toolbar={<Toolbar><Menu closeOnSelect={false}><MenuButton as={Button}>View</MenuButton><MenuList zIndex="dropdown"><MenuOptionGroupvalue={visibleColumns}type="checkbox"onChange={setVisibleColumns}close>{allColumns.map((c) => (<MenuItemOption key={c} value={c}>{c}</MenuItemOption>))}</MenuOptionGroup></MenuList></Menu></Toolbar>}/><PageBody p="0" contentWidth="full" position="relative"><DataGridcolumns={dataGrid.columns.concat()}data={dataGrid.data.concat()}isSelectablestate={{columnVisibility,}}/></PageBody></Page>)}
Custom icons#
Icons can be customized by passing a icons
map to the DataGrid
component.
icon | description |
---|---|
sortAscending | Sort ascending |
sortDescending | Sort descending |
rowExpanded | Expanded row |
rowCollapsed | Collapsed row |
import {Menu,MenuButton,MenuList,MenuOptionGroup,MenuOptionItem,Button,} from '@chakra-ui/react'import {Page,PageHeader,PageBody,Toolbar,DataGrid,} from '@saas-ui-pro/react'import { FiArrowUp, FiArrowDown, FiArrowRight } from 'react-icons/fi'const icons = {sortAscending: <FiArrowUp />,sortDescending: <FiArrowDown />,rowExpanded: <FiArrowDown />,rowCollapsed: <FiArrowRight />,}export default function CustomIcons() {return (<Page title="Customers" height="400px"><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><DataGridcolumns={dataGrid.columns.concat()}data={demoData}isSelectableisSortableisExpandableicons={icons}/></PageBody></Page>)}const demoData = dataGrid.data.map((row, i) => {return {...row,subRows: [{id: row.id + '-1',...row,},{id: row.id + '-2',...row,},],}})
SlotProps#
Using the slotProps
prop you can customize internal components (slots) of the DataGrid
component.
import {Page,PageHeader,PageBody,Toolbar,ToolbarButton,DataGrid,} from '@saas-ui-pro/react'export default function SlotProps() {return (<Page title="Customers" height="400px"><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><DataGridcolumns={dataGrid.columns.concat()}data={dataGrid.data.concat()}isSelectableslotProps={{row: ({ row, table }) => {return {bg: row.original.employees > 100 ? 'red.100' : 'transparent',_dark: {bg: row.original.employees > 100 ? 'red.700' : 'transparent',},}},cell: ({ cell, table }) => {return {fontWeight:cell.column.id === 'employees' ? 'semibold' : 'inherit',}},}}/></PageBody></Page>)}
Context Menu#
Using slotsProps
you can use the as
prop to customize the tr
element and wrap it with a ContextMenu
.
import {Portal} from '@chakra-ui/react'import {Page,PageHeader,PageBody,Toolbar,ToolbarButton,DataGrid,} from '@saas-ui-pro/react'import {ContextMenu,ContextMenuTrigger,ContextMenuList,ContextMenuItem} from '@saas-ui/react'export default function DataGridWithContextMenu() {return (<Page title="Customers" height="400px"><PageHeader title="Customers" /><PageBody p="0" contentWidth="full" position="relative"><DataGridcolumns={dataGrid.columns.concat()}data={dataGrid.data.concat()}slotProps={{row: () => ({as: RowWithContext,}),}}/></PageBody></Page>)}const RowWithContext = React.forwardRef<HTMLTableRowElement, TableRowProps>((props: TableRowProps, ref) => {return (<ContextMenu isLazy><ContextMenuTrigger as={Tr} ref={ref} {...props}/><Portal><ContextMenuList><MenuItem>Edit</MenuItem><MenuItem>Copy</MenuItem><MenuItem>Delete</MenuItem></ContextMenuList></Portal></ContextMenu>)})
Typescript#
To add typesafety for the meta properties, you need to add
react-table-config.d.ts
to yoursrc
. To use the default DataGrid config you can simply re-export the config from@saas-ui-pro/react
.
// Copy to: src/types/react-table-config.d.tsexport * from '@saas-ui-pro/react/src/data-grid/react-table-config.d'
import {ColumnDef,DataGrid,DataGridPagination,} from '@saas-ui-pro/react'interface ExampleData {id: stringname: stringemail: string}const columns: ColumnDef<ExampleData>[] = [{accessorKey: 'id',header: 'Id',},{accessorKey: 'name',header: 'Name',},{accessorKey: 'email',header: 'Email',},]const data: ExampleData[] = [{{id: '1',name: 'TaShya Charles',email: 'urna.nec.luctus@icloud.couk'},{id: '2',name: 'Donovan Mosley',email: 'lacinia.mattis.integer@icloud.couk',},}]<DataGrid<ExampleData> columns={columns} data={data} />
Was this helpful?