React Smart Table Component (DataTable)
Smart Table (DataTable)
A React Smart Table provides a full set of features for displaying and manipulating tabular data. It allows you to easily create dynamic and interactive tables with features such as sorting, filtering, pagination, and searching. React Smart Table Component (DataTables) makes it easy to work with large datasets, and it is widely used in a variety of applications, including web-based applications, e-commerce sites, and more.
Other frameworks
CoreUI components are available as native Angular, Bootstrap (Vanilla JS), and Vue components. To learn more please visit the following pages.
Features#
- Filter items by one or all columns
- Sort items by column
- Integrated with CPagination component by default
- Customize style of specific rows, columns and cells
- Customize display of columns
- Load with initial filters and sorter state
- Loading state visualization
- Default header labels generation based on column names
Usage#
Name | Registered | Role | Status | |||
---|---|---|---|---|---|---|
No items found | ||||||
Name | Registered | Role | Status |
const [details, setDetails] = useState([])const columns = [ { key: 'avatar', label: '', filter: false, sorter: false, }, { key: 'name', _style: { width: '20%' }, }, { key: 'registered', sorter: (date1, date2) => { const a = new Date(date1.registered) const b = new Date(date2.registered) return a > b ? 1 : b > a ? -1 : 0 } }, { key: 'role', _style: { width: '20%' } }, 'status', { key: 'show_details', label: '', _style: { width: '1%' }, filter: false, sorter: false, },]const items = [ { id: 1, name: 'Samppa Nori', avatar: '1.jpg', registered: '2021/03/01', role: 'Member', status: 'Active' }, { id: 2, name: 'Estavan Lykos', avatar: '2.jpg', registered: '2018/02/07', role: 'Staff', status: 'Banned' }, { id: 3, name: 'Chetan Mohamed', avatar: '3.jpg', registered: '2020/01/15', role: 'Admin', status: 'Inactive', _selected: true }, { id: 4, name: 'Derick Maximinus', avatar: '4.jpg', registered: '2019/04/05', role: 'Member', status: 'Pending' }, { id: 5, name: 'Friderik Dávid', avatar: '5.jpg', registered: '2022/03/25', role: 'Staff', status: 'Active' }, { id: 6, name: 'Yiorgos Avraamu', avatar: '6.jpg', registered: '2017/01/01', role: 'Member', status: 'Active' }, { id: 7, name: 'Avram Tarasios', avatar: '7.jpg', registered: '2016/02/12', role: 'Staff', status: 'Banned', _selected: true }, { id: 8, name: 'Quintin Ed', avatar: '8.jpg', registered: '2023/01/21', role: 'Admin', status: 'Inactive' }, { id: 9, name: 'Enéas Kwadwo', avatar: '9.jpg', registered: '2024/03/10', role: 'Member', status: 'Pending' }, { id: 10, name: 'Agapetus Tadeáš', avatar: '10.jpg', registered: '2015/01/10', role: 'Staff', status: 'Active' }, { id: 11, name: 'Carwyn Fachtna', avatar: '11.jpg', registered: '2014/04/01', role: 'Member', status: 'Active' }, { id: 12, name: 'Nehemiah Tatius', avatar: '12.jpg', registered: '2013/01/05', role: 'Staff', status: 'Banned', _selected: true }, { id: 13, name: 'Ebbe Gemariah', avatar: '13.jpg', registered: '2012/02/25', role: 'Admin', status: 'Inactive' }, { id: 14, name: 'Eustorgios Amulius', avatar: '14.jpg', registered: '2011/03/19', role: 'Member', status: 'Pending' }, { id: 15, name: 'Leopold Gáspár', avatar: '15.jpg', registered: '2010/02/01', role: 'Staff', status: 'Active' }]const getBadge = (status) => { switch (status) { case 'Active': return 'success' case 'Inactive': return 'secondary' case 'Pending': return 'warning' case 'Banned': return 'danger' default: return 'primary' }}const toggleDetails = (index) => { const position = details.indexOf(index) let newDetails = details.slice() if (position !== -1) { newDetails.splice(position, 1) } else { newDetails = [...details, index] } setDetails(newDetails)}return ( <CSmartTable activePage={2} cleaner clickableRows columns={columns} columnFilter columnSorter footer items={items} itemsPerPageSelect itemsPerPage={5} pagination onFilteredItemsChange={(items) => { console.log(items) }} onSelectedItemsChange={(items) => { console.log(items) }} scopedColumns={{ avatar: (item) => ( <td> <CAvatar src={`./../../images/avatars/${item.avatar}`} /> </td> ), registered: (item) => { const date = new Date(item.registered) const options = { year: 'numeric', month: 'long', day: 'numeric', } return ( <td>{date.toLocaleDateString('en-US', options)}</td> ) }, status: (item) => ( <td> <CBadge color={getBadge(item.status)}>{item.status}</CBadge> </td> ), show_details: (item) => { return ( <td className="py-2"> <CButton color="primary" variant="outline" shape="square" size="sm" onClick={() => { toggleDetails(item.id) }} > {details.includes(item.id) ? 'Hide' : 'Show'} </CButton> </td> ) }, details: (item) => { return ( <CCollapse visible={details.includes(item.id)}> <CCardBody className="p-3"> <h4>{item.user}</h4> <p className="text-body-secondary">User since: {item.registered}</p> <CButton size="sm" color="info"> User Settings </CButton> <CButton size="sm" color="danger" className="ms-1"> Delete </CButton> </CCardBody> </CCollapse> ) }, }} selectable sorterValue={{ column: 'status', state: 'asc' }} tableFilter tableProps={{ className: 'add-this-class', responsive: true, striped: true, hover: true, }} tableBodyProps={{ className: 'align-middle' }} />)
Column names#
By default, React Table component will generate the header labels for each column based on the column's data source.
No items found |
const items = [ { id: 0, name: 'John Doe', registered: '2022/01/01', role: 'Guest', status: 'Pending' }, { id: 1, name: 'Samppa Nori', registered: '2022/01/01', role: 'Member', status: 'Active', _props: { color: 'primary', align: 'middle' }, }, { id: 2, name: 'Estavan Lykos', registered: '2022/02/07', role: 'Staff', status: 'Banned', _cellProps: { all: { className: 'fw-semibold' }, name: { color: 'info' } }, }, { id: 3, name: 'Chetan Mohamed', registered: '2022/02/07', role: 'Admin', status: 'Inactive', }, { id: 4, name: 'Derick Maximinus', registered: '2022/03/19', role: 'Member', status: 'Pending', }, { id: 5, name: 'Friderik Dávid', registered: '2022/01/21', role: 'Staff', status: 'Active' }, { id: 6, name: 'Yiorgos Avraamu', registered: '2022/01/01', role: 'Member', status: 'Active', }, { id: 7, name: 'Avram Tarasios', registered: '2022/02/07', role: 'Staff', status: 'Banned', _props: { color: 'warning', align: 'middle' }, }, { id: 8, name: 'Quintin Ed', registered: '2022/02/07', role: 'Admin', status: 'Inactive' }, { id: 9, name: 'Enéas Kwadwo', registered: '2022/03/19', role: 'Member', status: 'Pending' }, { id: 10, name: 'Agapetus Tadeáš', registered: '2022/01/21', role: 'Staff', status: 'Active', }, { id: 11, name: 'Carwyn Fachtna', registered: '2022/01/01', role: 'Member', status: 'Active', }, { id: 12, name: 'Nehemiah Tatius', registered: '2022/02/07', role: 'Staff', status: 'Banned', }, { id: 13, name: 'Ebbe Gemariah', registered: '2022/02/07', role: 'Admin', status: 'Inactive', }, { id: 14, name: 'Eustorgios Amulius', registered: '2022/03/19', role: 'Member', status: 'Pending', }, { id: 15, name: 'Leopold Gáspár', registered: '2022/01/21', role: 'Staff', status: 'Active' }, { id: 16, name: 'Pompeius René', registered: '2022/01/01', role: 'Member', status: 'Active' }, { id: 17, name: 'Paĉjo Jadon', registered: '2022/02/07', role: 'Staff', status: 'Banned' }, { id: 18, name: 'Micheal Mercurius', registered: '2022/02/07', role: 'Admin', status: 'Inactive', }, { id: 19, name: 'Ganesha Dubhghall', registered: '2022/03/19', role: 'Member', status: 'Pending', }, { id: 20, name: 'Hiroto Šimun', registered: '2022/01/21', role: 'Staff', status: 'Active' }, { id: 21, name: 'Vishnu Serghei', registered: '2022/01/01', role: 'Member', status: 'Active', }, { id: 22, name: 'Zbyněk Phoibos', registered: '2022/02/07', role: 'Staff', status: 'Banned' }, { id: 23, name: 'Aulus Agmundr', registered: '2022/01/01', role: 'Member', status: 'Pending', }, { id: 42, name: 'Ford Prefect', registered: '2001/05/25', role: 'Alien', status: "Don't panic!", },]return ( <CSmartTable items={items} columnFilter columnSorter pagination tableProps={{ hover: true, }} />)
Column groups#
The React Smart Table component allows users to group related columns under a common header. This can be useful when displaying data that has multiple categories or when comparing different sets of data. When the Smart Table is rendered, the header group will be displayed as a single header cell that spans the width of the columns included in the group. The group header cells feature can help to make the Smart Table component more organized and easier to read by grouping related data together and making it more visually distinct from other columns.
Group 1 | |||
---|---|---|---|
Subgroup 1 | Subgroup 2 | ||
Subgroup 1A | Subgroup 1B | Subgroup 2A | |
Name | Registered | Role | Status |
No items found | |||
Name | Registered | Role | Status |
const columns = [ { group: 'Group 1', children: [ { group: 'Subgroup 1', children: [ { group: 'Subgroup 1A', children: [ { key: 'name', _style: { width: '20%' }, }, 'registered', ], }, { group: 'Subgroup 1B', children: [{ key: 'role', _style: { width: '20%' } }], }, ], }, { group: 'Subgroup 2', children: [ { group: 'Subgroup 2A', children: [{ key: 'status', _style: { width: '20%' } }], }, ], }, ], },]const items = [ { id: 0, name: 'John Doe', registered: '2022/01/01', role: 'Guest', status: 'Pending', }, { id: 1, name: 'Samppa Nori', registered: '2022/01/01', role: 'Member', status: 'Active', }, { id: 2, name: 'Estavan Lykos', role: 'Staff', status: 'Banned', _cellProps: { name: { colSpan: 2 } }, }, { id: 3, name: 'Chetan Mohamed', registered: '2022/02/07', role: 'Admin', status: 'Inactive', }, { id: 4, name: 'Derick Maximinus', registered: '2022/03/19', role: 'Member', status: 'Pending', }, { id: 5, name: 'Friderik Dávid', registered: '2022/01/21', role: 'Staff', status: 'Active', },]return <CSmartTable columns={columns} columnFilter columnSorter items={items} />
Table with headers spanning multiple rows or columns#
In the example below, the table consists of two individual columns and one column group spanning three columns. It has six rows. Two headers that span multiple rows.
Poster availability | ||||
---|---|---|---|---|
Poster name | Color | Sizes available | ||
No items found |
const columns = [ { group: 'Poster availability', _props: { colSpan: 5 }, children: [ { key: 'poster', label: 'Poster name', _props: { scope: 'col' }, }, { key: 'color', _props: { scope: 'col' }, }, { key: 'size', label: 'Sizes available', _props: { colSpan: 3, scope: 'colgroup' }, _style: { width: '50%' }, }, ], },]const items = [ { poster: 'Zodiac', color: 'Full color', size: ['A2', 'A3', 'A4'], _cellProps: { color: { color: 'light', scope: 'row' }, poster: { color: 'light', rowSpan: 3, scope: 'rowgroup' }, }, }, { color: 'Black and white', size: ['A1', 'A2', 'A3'], _cellProps: { color: { color: 'light', scope: 'row' } }, }, { color: 'Sepia', size: ['A3', 'A4', 'A5'], _cellProps: { color: { color: 'light', scope: 'row' } }, }, { poster: 'Angels', color: 'Black and white', size: ['A1', 'A3', 'A4'], _cellProps: { color: { color: 'light', scope: 'row' }, poster: { color: 'light', rowSpan: 2, scope: 'rowgroup' }, }, }, { color: 'Sepia', size: ['A2', 'A3', 'A5'], _cellProps: { color: { color: 'light', scope: 'row' } }, },]return ( <CSmartTable columns={columns} items={items} tableHeadProps={{ color: 'light', }} tableProps={{ bordered: true, }} scopedColumns={{ size: (item) => ( <> {item.size.map((_item) => ( <td>{_item}</td> ))} </> ), }} />)
Example source: https://www.w3.org/WAI/tutorials/tables/irregular/
Column sorter#
The column sorter feature enables sorting React.js table data by column values. You can enable sorting by adding columnSorter
to <CSmartTable>
. If you want to disable sorting for a specific column, add sorter: false
to the desired column.
Name | Registered | Role | |
---|---|---|---|
No items found |
const columns = [ { key: 'avatar', label: '', sorter: false, }, { key: 'name', _style: { width: '30%' }, }, { key: 'registered', sorter: (date1, date2) => { const a = new Date(date1.registered) const b = new Date(date2.registered) return a > b ? 1 : b > a ? -1 : 0 } }, 'role']const items = [ { id: 1, name: 'Samppa Nori', avatar: '1.jpg', registered: '2021/03/01', role: 'Member', }, { id: 2, name: 'Estavan Lykos', avatar: '2.jpg', registered: '2018/02/07', role: 'Staff', }, { id: 3, name: 'Chetan Mohamed', avatar: '3.jpg', registered: '2020/01/15', role: 'Admin', _selected: true }, { id: 4, name: 'Derick Maximinus', avatar: '4.jpg', registered: '2019/04/05', role: 'Member', }, { id: 5, name: 'Friderik Dávid', avatar: '5.jpg', registered: '2022/03/25', role: 'Staff', }, { id: 6, name: 'Yiorgos Avraamu', avatar: '6.jpg', registered: '2017/01/01', role: 'Member', }, { id: 7, name: 'Avram Tarasios', avatar: '7.jpg', registered: '2016/02/12', role: 'Staff', _selected: true }, { id: 8, name: 'Quintin Ed', avatar: '8.jpg', registered: '2023/01/21', role: 'Admin', }, { id: 9, name: 'Enéas Kwadwo', avatar: '9.jpg', registered: '2024/03/10', role: 'Member', }, { id: 10, name: 'Agapetus Tadeáš', avatar: '10.jpg', registered: '2015/01/10', role: 'Staff', }, { id: 11, name: 'Carwyn Fachtna', avatar: '11.jpg', registered: '2014/04/01', role: 'Member', }, { id: 12, name: 'Nehemiah Tatius', avatar: '12.jpg', registered: '2013/01/05', role: 'Staff', _selected: true }, { id: 13, name: 'Ebbe Gemariah', avatar: '13.jpg', registered: '2012/02/25', role: 'Admin', }, { id: 14, name: 'Eustorgios Amulius', avatar: '14.jpg', registered: '2011/03/19', role: 'Member', }, { id: 15, name: 'Leopold Gáspár', avatar: '15.jpg', registered: '2010/02/01', role: 'Staff', }]return ( <CSmartTable columns={columns} columnSorter={{ multiple: true, resetable: true, }} items={items} itemsPerPageSelect itemsPerPage={5} pagination scopedColumns={{ avatar: (item) => ( <td> <CAvatar src={`./../../images/avatars/${item.avatar}`} /> </td> ), }} sorterValue={[ { column: 'role', state: 'asc' }, { column: 'registered', state: 'desc' }, ]} tableBodyProps={{ className: 'align-middle' }} />)
Sort multiple columns#
Enables sorting by multiple columns simultaneously by adding columnSorter={{ multiple: true }}
The sorting order will be maintained across multiple columns based on the order of user interaction. This means you can sort by multiple columns, and each column will keep its order.
<CSmartTable columns={[...]} columnSorter={{ multiple: true }} items={[...]}/>
Resetable sorter state#
When columnSorter={{ resetable: true }}
is set, clicking the sorter toggles through three states: ascending, descending, and unsorted. After the third click, it resets the sorting, returning the table to its initial state.
<CSmartTable columns={[...]} columnSorter={{ resetable: true }} items={[...]}/>
Custom sorter#
By default, sorting is done automatically by the component and works as expected when the values in the column are of a single data type: either string (case-insensitive) or number.
In case you want to sort non-string and non-number data, define a custom sorting function for the column. You can use this option to control how the values are compared and sorted. The function receives two arguments (a
, b
) corresponding to two row values and must return:
- a negative value if
a
should appear beforeb
, - zero if
a
andb
are equal, - a positive value if
a
should appear afterb
.
<CSmartTable columns={[ ... { key: 'registered', sorter: (date1, date2) => { const a = new Date(date1.registered) const b = new Date(date2.registered) return a > b ? 1 : b > a ? -1 : 0 } }, ... ]} items={[...]}/>
Column filter#
The column filter feature allows filtering React.js table data based on column values. To enable filtering, add columnFilter
to the <CSmartTable>
component. If you want to disable filtering for a specific column, use filter: false
in the column's configuration.
Name | Registered | Role | |
---|---|---|---|
No items found |
const columns = [ { key: 'avatar', label: '', filter: false, }, { key: 'name', _style: { width: '30%' }, }, 'registered', { key: 'role', filter: false, },]const items = [ { id: 1, name: 'Samppa Nori', avatar: '1.jpg', registered: '2021/03/01', role: 'Member', }, { id: 2, name: 'Estavan Lykos', avatar: '2.jpg', registered: '2018/02/07', role: 'Staff', }, { id: 3, name: 'Chetan Mohamed', avatar: '3.jpg', registered: '2020/01/15', role: 'Admin', _selected: true }, { id: 4, name: 'Derick Maximinus', avatar: '4.jpg', registered: '2019/04/05', role: 'Member', }, { id: 5, name: 'Friderik Dávid', avatar: '5.jpg', registered: '2022/03/25', role: 'Staff', }, { id: 6, name: 'Yiorgos Avraamu', avatar: '6.jpg', registered: '2017/01/01', role: 'Member', }, { id: 7, name: 'Avram Tarasios', avatar: '7.jpg', registered: '2016/02/12', role: 'Staff', _selected: true }, { id: 8, name: 'Quintin Ed', avatar: '8.jpg', registered: '2023/01/21', role: 'Admin', }, { id: 9, name: 'Enéas Kwadwo', avatar: '9.jpg', registered: '2024/03/10', role: 'Member', }, { id: 10, name: 'Agapetus Tadeáš', avatar: '10.jpg', registered: '2015/01/10', role: 'Staff', }, { id: 11, name: 'Carwyn Fachtna', avatar: '11.jpg', registered: '2014/04/01', role: 'Member', }, { id: 12, name: 'Nehemiah Tatius', avatar: '12.jpg', registered: '2013/01/05', role: 'Staff', _selected: true }, { id: 13, name: 'Ebbe Gemariah', avatar: '13.jpg', registered: '2012/02/25', role: 'Admin', }, { id: 14, name: 'Eustorgios Amulius', avatar: '14.jpg', registered: '2011/03/19', role: 'Member', }, { id: 15, name: 'Leopold Gáspár', avatar: '15.jpg', registered: '2010/02/01', role: 'Staff', }]return ( <CSmartTable columns={columns} columnFilter items={items} itemsPerPageSelect itemsPerPage={5} pagination scopedColumns={{ avatar: (item) => ( <td> <CAvatar src={`./../../images/avatars/${item.avatar}`} /> </td> ), }} tableBodyProps={{ className: 'align-middle' }} />)
Custom filters#
CoreUI React Smart Table (React DataTables) provides the ability to use custom filtering functions. Custom filters offer advanced filtering capabilities. You can define and integrate custom filtering logic by adding a filter
function to the desired column, enabling more complex data filtering strategies.
Date Range Picker#
Here is an example of how you might use the <CDateRangePicker />
component to apply custom filters to a React DataTable component:
Name | Registered |
---|---|
No items found |
const items = [ { id: 0, name: 'John Doe', registered: '2022/01/01' }, { id: 1, name: 'Samppa Nori', registered: '2022/01/01', }, { id: 2, name: 'Estavan Lykos', registered: '2022/02/07', }, { id: 3, name: 'Chetan Mohamed', registered: '2022/02/07' }, { id: 4, name: 'Derick Maximinus', registered: '2022/03/19', }, { id: 5, name: 'Friderik Dávid', registered: '2022/01/21' }, { id: 6, name: 'Yiorgos Avraamu', registered: '2022/01/01' }, { id: 7, name: 'Avram Tarasios', registered: '2022/02/07', }, { id: 8, name: 'Quintin Ed', registered: '2022/02/07' }, { id: 9, name: 'Enéas Kwadwo', registered: '2022/03/19', role: 'Member', status: 'Pending' }, { id: 10, name: 'Agapetus Tadeáš', registered: '2022/01/21' }, { id: 11, name: 'Carwyn Fachtna', registered: '2022/01/01' }, { id: 12, name: 'Nehemiah Tatius', registered: '2022/02/07' }, { id: 13, name: 'Ebbe Gemariah', registered: '2022/02/07' }, { id: 14, name: 'Eustorgios Amulius', registered: '2022/03/19', }, { id: 15, name: 'Leopold Gáspár', registered: '2022/01/21' }, { id: 16, name: 'Pompeius René', registered: '2022/01/01' }, { id: 17, name: 'Paĉjo Jadon', registered: '2022/02/07' }, { id: 18, name: 'Micheal Mercurius', registered: '2022/02/07', }, { id: 19, name: 'Ganesha Dubhghall', registered: '2022/03/19', }, { id: 20, name: 'Hiroto Šimun', registered: '2022/01/21' }, { id: 21, name: 'Vishnu Serghei', registered: '2022/01/01' }, { id: 22, name: 'Zbyněk Phoibos', registered: '2022/02/07' }, { id: 23, name: 'Aulus Agmundr', registered: '2022/01/01', }, { id: 42, name: 'Ford Prefect', registered: '2022/05/25', },]const [startDate, setStartDate] = useState(new Date('2022-01-01'))const [endDate, setEndDate] = useState(new Date('2022-03-19'))const minDate = new Date( Math.min( ...items.map((element) => { return new Date(Date.parse(element.registered)) }), ),)const maxDate = new Date( Math.max( ...items.map((element) => { return new Date(Date.parse(element.registered)) }), ),)const columns = [ { key: 'name', _style: { width: '50%' }, }, { key: 'registered', _style: { width: '50%' }, filter: (values, onChange) => { return ( <CDateRangePicker footer size="sm" startDate={startDate} endDate={endDate} minDate={minDate} maxDate={maxDate} onStartDateChange={(date) => { setStartDate(date) onChange((item) => { if (date) { const itemDate = new Date(Date.parse(item)) return endDate ? itemDate >= date && itemDate <= endDate : itemDate >= date } return true }) }} onEndDateChange={(date) => { setEndDate(date) onChange((item) => { if (date) { const itemDate = new Date(Date.parse(item)) return startDate ? itemDate <= date && itemDate >= startDate : itemDate <= date } return true }) }} /> ) }, },]const convertToDate = (date) => { const _date = new Date(Date.parse(date)) return _date.toLocaleDateString()}return ( <CSmartTable columns={columns} columnFilter columnFilterValue={{ registered: (date) => new Date(Date.parse(date)) >= startDate && new Date(Date.parse(date)) <= endDate, }} columnSorter items={items} itemsPerPageSelect itemsPerPage={5} pagination scopedColumns={{ registered: (item) => <td>{convertToDate(item.registered)}</td>, }} />)
Multi Select#
Here is an example of how you might use the <CMultiSelect />
component to apply custom filters to a React DataTable:
Name | Role |
---|---|
No items found |
const columns = [ { key: 'name', _style: { width: '50%' }, }, { key: 'role', _style: { width: '50%' }, filter: (values, onChange) => { const unique = [...new Set(values)].sort() return ( <CMultiSelect size="sm" onChange={(selected) => { const _selected = selected.map((element) => { return element.value }) onChange((item) => { return Array.isArray(_selected) && _selected.length ? _selected.includes(item.toLowerCase()) : true }) }} options={unique.map((element) => { return { value: element.toLowerCase(), label: element, } })} /> ) }, sorter: false, },]const items = [ { id: 0, name: 'John Doe', role: 'Guest' }, { id: 1, name: 'Samppa Nori', role: 'Member', }, { id: 2, name: 'Estavan Lykos', role: 'Staff', }, { id: 3, name: 'Chetan Mohamed', role: 'Admin' }, { id: 4, name: 'Derick Maximinus', role: 'Member', }, { id: 5, name: 'Friderik Dávid', role: 'Staff' }, { id: 6, name: 'Yiorgos Avraamu', role: 'Member' }, { id: 7, name: 'Avram Tarasios', role: 'Staff', }, { id: 8, name: 'Quintin Ed', role: 'Admin' }, { id: 9, name: 'Enéas Kwadwo', role: 'Member' }, { id: 10, name: 'Agapetus Tadeáš', role: 'Staff' }, { id: 11, name: 'Carwyn Fachtna', role: 'Member' }, { id: 12, name: 'Nehemiah Tatius', role: 'Staff' }, { id: 13, name: 'Ebbe Gemariah', role: 'Admin' }, { id: 14, name: 'Eustorgios Amulius', role: 'Member', }, { id: 15, name: 'Leopold Gáspár', role: 'Staff' }, { id: 16, name: 'Pompeius René', role: 'Member' }, { id: 17, name: 'Paĉjo Jadon', role: 'Staff' }, { id: 18, name: 'Micheal Mercurius', role: 'Admin', }, { id: 19, name: 'Ganesha Dubhghall', role: 'Member', }, { id: 20, name: 'Hiroto Šimun', role: 'Staff' }, { id: 21, name: 'Vishnu Serghei', role: 'Member' }, { id: 22, name: 'Zbyněk Phoibos', role: 'Staff' }, { id: 23, name: 'Aulus Agmundr', role: 'Member', }, { id: 42, name: 'Ford Prefect', role: 'Alien', },]return ( <CSmartTable columns={columns} columnFilter columnSorter items={items} itemsPerPageSelect itemsPerPage={10} pagination />)
Data sources#
You can use Fetch API to load data from different sources and then pass them to <CSmartTable>
External Data (10.000+ records)#
One of the key features of React Smart Table (React DataTables) is the ability to load data from an external source, such as an API or a server-side script. This can be useful if you have a large amount of data that you don't want to load all at once. To load external data into a React Smart Table (React DataTables), you can use the Fetch API to the data source.
Here is an example of how you might use React Smart Table with external data:
First Name | Last Name | Email | Country | IP |
---|---|---|---|---|
No items found | ||||
First Name | Last Name | Email | Country | IP |
const [activePage, setActivePage] = useState(3)const [columnFilter, setColumnFilter] = useState({})const [columnSorter, setColumnSorter] = useState(null)const [itemsPerPage, setItemsPerPage] = useState(10)const [loading, setLoading] = useState(false)const [users, setUsers] = useState([])const [records, setRecords] = useState(0)
const columns = [ { key: 'first_name', _style: { minWidth: '130px' } }, { key: 'last_name', _style: { minWidth: '130px' } }, 'email', { key: 'country', _style: { minWidth: '120px' } }, { key: 'ip_address', label: 'IP' },]
useEffect(() => { const fetchData = async () => { try { setLoading(true) const offset = (activePage - 1) * itemsPerPage let params = new URLSearchParams()
Object.keys(columnFilter).forEach((key) => { params.append(key, columnFilter[key]) })
if (columnSorter?.column) { params.append('sort', `${columnSorter.column}%${columnSorter.state}`) }
const response = await fetch( `https://apitest.coreui.io/demos/users?offset=${offset}&limit=${itemsPerPage}&${params}` )
const result = await response.json()
setRecords(result.number_of_matching_records) setUsers(result.number_of_matching_records ? result.records : []) } catch (error) { console.error('Error fetching users:', error) setUsers([]) // Optionally show an error state } finally { setLoading(false) } }
fetchData()}, [activePage, columnFilter, columnSorter, itemsPerPage])
return ( <CSmartTable columns={columns} columnFilter={{ external: true }} columnSorter={{ external: true }} footer items={users} itemsPerPage={itemsPerPage} itemsPerPageSelect loading={loading} pagination={{ external: true, }} paginationProps={{ activePage, pages: records > 0 ? Math.ceil(records / itemsPerPage) : 1, }} tableProps={{ hover: true, responsive: true, }} onActivePageChange={(page) => setActivePage(page)} onColumnFilterChange={(filter) => { setActivePage(1) setColumnFilter(filter) }} onItemsPerPageChange={(pageSize) => { setActivePage(1) setItemsPerPage(pageSize) }} onSorterChange={(sorter) => setColumnSorter(sorter)} />)
JSON (10.000+ records)#
The Fetch API can be used to load JSON data by making a GET request to the endpoint where the data is located.
In this example, the fetch()
method is used to make a GET request to the endpoint https://apitest.coreui.io/fake_data/users.json
, which returns a response.
The response.json()
method is then used to parse the response as a JSON object.
The resulting JSON object is stored in the users
and loaded by <CSmartTable />
.
First Name | Last Name | Email | Country | IP |
---|---|---|---|---|
No items found | ||||
First Name | Last Name | Email | Country | IP |
const [loading, setLoading] = useState(false)const [users, setUsers] = useState([])
const columns = [ { key: 'first_name', _style: { minWidth: '130px' } }, { key: 'last_name', _style: { minWidth: '130px' } }, 'email', { key: 'country', _style: { minWidth: '120px' } }, { key: 'ip_address', label: 'IP' },]
useEffect(() => { const fetchData = async () => { try { setLoading(true) const response = await fetch('https://apitest.coreui.io/fake_data/users.json') const result = await response.json() setUsers(result) } catch (error) { console.error('Error fetching user data:', error) setUsers([]) // Optionally handle error state } finally { setLoading(false) } }
fetchData()}, [])
return ( <CSmartTable columns={columns} columnFilter columnSorter footer items={users} itemsPerPageSelect loading={loading} pagination tableProps={{ hover: true, responsive: true, }} />)
API#
CSmartTable#
import { CSmartTable } from '@coreui/react-pro'// orimport CSmartTable from '@coreui/react-pro/src/components/smart-table/CSmartTable'
Property | Description | Type | Default |
---|---|---|---|
activePage | Sets active page. If 'pagination' prop is enabled, activePage is set only initially. | number | 1 |
cleaner | When set, displays table cleaner above table, next to the table filter (or in place of table filter if tableFilter prop is not set)Cleaner resets tableFilterValue , columnFilterValue , sorterValue . If clean is possible it is clickable (tabIndex="0" role="button" , color="danger" ), otherwise it is not clickable and transparent. Cleaner can be customized through the cleaner slot. | boolean | - |
clickableRows | Style table items as clickable. | boolean | - |
columnFilter | When set, displays additional filter row between table header and items, allowing filtering by specific column. Column filter can be customized, by passing prop as object with additional options as keys. Available options: - external (Boolean) - Disables automatic filtering inside component. - lazy (Boolean) - Set to true to trigger filter updates only on change event. | boolean | ColumnFilter | - |
columnFilterValue | Value of table filter. To set pass object where keys are column names and values are filter strings e.g.:{ user: 'John', age: 12 } | ColumnFilterValue | - |
columnSorter | Enables table sorting by column value. Sorting will be performed corectly only if values in column are of one type: string (case insensitive) or number. Sorter can be customized, by passing prop as object with additional options as keys. Available options: - external (Boolean) - Disables automatic sorting inside the component, allowing for external sorting control. - multiple (Boolean) - Enables sorting by multiple columns simultaneously. The sorting order will be maintained across multiple columns based on the order of interaction. - resetable (Boolean) - If set to true, clicking on the sorter cycles through three states: ascending, descending, and null (no sorting). The third click on the sorter will reset the sorting and restore the table to its original order. | boolean | Sorter | - |
columns | Prop for table columns configuration. If prop is not defined, table will display columns based on the first item keys, omitting keys that begins with underscore (e.g. '_classes') In columns prop each array item represents one column. Item might be specified in two ways: String: each item define column name equal to item value. Object: item is object with following keys available as column configuration: - key (required)(String) - define column name equal to item key. - label (String) - define visible label of column. If not defined, label will be generated automatically based on column name, by converting kebab-case and snake_case to individual words and capitalization of each word. - _classes (String/Array/Object) - adds classes to all cels in column - _style (String/Array/Object) - adds styles to the column header (useful for defining widths) - sorter (Boolean) - disables sorting of the column when set to false - filter (Boolean) - removes filter from column when set to false. | (string | Column)[] | - |
elementCover 4.9.0+ | ReactNode for passing custom CElementCover content. | ReactNode | - |
footer | If true Displays table footer, which mirrors table header. (without column filter).Or Array of objects or strings, where each element represents one cell in the table footer. Example items: ['FooterCell', 'FooterCell', 'FooterCell'] or [{ label: 'FooterCell', _props: { color: 'success' }, ...] | boolean | (string | FooterItem)[] | - |
header | Set to false to remove table header. | boolean | true |
items 4.9.0+ | Array of objects, where each object represents one item - row in table. Additionally, you can add style classes to each row by passing them by '_props' key and to single cell by '_cellProps'. Example item: { name: 'John' , age: 12, _props: { color: 'success' }, _cellProps: { age: { className: 'fw-bold'}}} | Item[] | [] |
itemsNumber | The total number of items. Use if you pass a portion of data from an external source to let know component what is the total number of items. | number | - |
itemsPerPage | Number of items per site, when pagination is enabled. | number | 10 |
itemsPerPageLabel | Label for items per page selector. | string | Items per page: |
itemsPerPageOptions | Items per page selector options. | number[] | [5, 10, 20, 50] |
itemsPerPageSelect | Adds select element over table, which is used for control items per page in pagination. If you want to customize this element, pass object with optional values: - external (Boolean) - disables automatic 'itemsPerPage' change. | boolean | ItemsPerPageSelect | - |
loading | When set, table will have loading style: loading spinner and reduced opacity. | boolean | - |
noItemsLabel | ReactNode or string for passing custom noItemsLabel texts. | ReactNode | No items found |
onActivePageChange | Page change callback. | (value: number) => void | - |
onColumnFilterChange | Column filter change callback. | (value: ColumnFilterValue) => void | - |
onFilteredItemsChange | Filtered items change callback. | (items: Item[]) => void | - |
onItemsPerPageChange | Pagination change callback. | (value: number) => void | - |
onRowClick | Row click callback. | (item: Item, index: number, columnName: string, event: boolean | MouseEvent<Element, MouseEvent>) => void | - |
onSelectAll 4.9.0+ | Select all callback. | () => void | - |
onSelectedItemsChange | Selected items change callback. | (items: Item[]) => void | - |
onSorterChange | Sorter value change callback. | (value: SorterValue | SorterValue[]) => void | - |
onTableFilterChange | Table filter change callback. | (value?: string) => void | - |
pagination | Enables default pagination. Set to true for default setup or pass an object with additional CPagination props. Default pagination will always have the computed number of pages that cannot be changed. The number of pages is generated based on the number of passed items and 'itemsPerPage' prop. If this restriction is an obstacle, you can make external CPagination instead. | boolean | Pagination | - |
paginationProps | Properties to CSmartPagination component - https://coreui.io/react/docs/components/smart-pagination#csmartpagination | CSmartPaginationProps | - |
scopedColumns | Scoped columns. | ScopedColumns | - |
selectAll 4.9.0+ | Enables select all checkbox displayed in the header of the table. Can be customized, by passing prop as object with additional options as keys. Available options: - external (Boolean) - Disables automatic selection inside the component. | boolean | { external?: boolean; } | true |
selectable | Add checkboxes to make table rows selectable. | boolean | - |
selected 4.9.0+ | Array of selected objects, where each object represents one item - row in table. Example item: { name: 'John' , age: 12 } | Item[] | - |
sorterValue | State of the sorter. Name key is column name, direction can be 'asc' or 'desc'. | SorterValue | SorterValue[] | - |
sortingIcon | Sorter icon when items are unsorted. | ReactNode | <CIcon width={18} icon={cilSwapVertical} key="csv" /> |
sortingIconAscending | Sorter icon when items are sorted ascending. | ReactNode | <CIcon width={18} icon={cilArrowTop} key="cat" /> |
sortingIconDescending | Sorter icon when items are sorted descending. | ReactNode | <CIcon width={18} icon={cilArrowBottom} key="cab" /> |
tableBodyProps | Properties to CTableBody component - https://coreui.io/react/docs/components/table/#ctablebody | CTableBodyProps | - |
tableFilter | When set, displays table filter above table, allowing filtering by specific column. Column filter can be customized, by passing prop as object with additional options as keys. Available options: - external (Boolean) - Disables automatic filtering inside component. - lazy (Boolean) - Set to true to trigger filter updates only on change event. | boolean | TableFilter | - |
tableFilterLabel | The element represents a caption for a component. | string | Filter: |
tableFilterPlaceholder | Specifies a short hint that is visible in the search input. | string | type string... |
tableFilterValue | Value of table filter. | string | - |
tableFootProps | Properties to CTableFoot component - https://coreui.io/react/docs/components/table/#ctablefoot | CTableFootProps | - |
tableHeadProps | Properties to CTableHead component - https://coreui.io/react/docs/components/table/#ctablehead | CTableHeadProps | - |
tableProps | Properties to CTable component - https://coreui.io/react/docs/components/table/#ctable | CTableProps | - |