Material-UI is a UI library providing predefined robust and customizable components for React for easier web development. The MUI design is based on top of Material Design by Google.
In this tutorial, we are going to discuss the React MUI TableSortLabel API. The sorting feature can be implemented in the Tables using the TableSortLabel. The API provides a lot of functionality and we are going to learn to implement them.
Import TableSortLabel API
import TableSortLabel from '@mui/material/TableSortLabel'; // or import { TableSortLabel } from '@mui/material';
Props List: Here is the list of different props used with this component. We can access them and modify them according to our needs.
- children: It is a component similar to the table row.
- classes: This overrides the existing styles or adds new styles to the component.
- sx: The system prop allows defining system overrides as well as additional CSS styles.
- active: If set to true, the label will have an active styling.
- direction(asc/desc): IT takes the direction of sorting.
- hideSortIcon: If true, it hides the sort icon.
- IconComponent: It is the icon of the TableSortLable.
Syntax: Create the TableSortLabel component as follows:
<TableSortLabel active={orderBy === headCell.id} direction={orderBy === headCell.id ? order : 'asc'} onClick={createSortHandler(headCell.id)} > {headCell.label} {orderBy === headCell.id ? ( <Box component="span" sx={visuallyHidden}> {order === 'desc' ? 'sorted descending' : 'sorted ascending'} </Box> ) : null} </TableSortLabel>
Installing and Creating React app, and adding the MUI dependencies.
Step 1: Create a react project using the following command.
npx create-react-app gfg_tutorial
Step 2: Get into the project directory
cd gfg_tutorial
Step 3: Install the MUI dependencies as follows:
npm install @mui/material @emotion/react @emotion/styled @mui/lab
Step 4: Run the project as follows:
npm start
Example 1: In the following example, we have a Table with TableSortLabel.
App.js
import * as React from 'react' import PropTypes from 'prop-types' import { Box, Table, TableRow, TableCell, TableHead, TableContainer, TableBody, TableSortLabel, Paper, Toolbar, } from '@mui/material' import { visuallyHidden } from '@mui/utils' function App() { return ( <div className= "App" > <div className= "head" style={{ width: 'fit-content' , margin: 'auto' , }} > <h1 style={{ color: 'green' , }} > neveropen </h1> <strong>React MUI TableSortLabel API</strong> </div> <TableSorter /> </div> ) } function createData(name, likes) { return { name, likes, } } const rows = [ createData( 'C++' , 305), createData( 'Java' , 452), createData( 'Python' , 262), createData( 'React' , 159), createData( 'Rust' , 356), ] function descendingComparator(a, b, orderBy) { if (b[orderBy] < a[orderBy]) { return -1 } if (b[orderBy] > a[orderBy]) { return 1 } return 0 } function getComparator(order, orderBy) { return order === 'desc' ? (a, b) => descendingComparator(a, b, orderBy) : (a, b) => -descendingComparator(a, b, orderBy) } // This method is created for cross-browser // compatibility, if you don't need to support IE11, // you can use Array.prototype.sort() directly function stableSort(array, comparator) { const stabilizedThis = array.map((el, index) => [el, index]) stabilizedThis.sort((a, b) => { const order = comparator(a[0], b[0]) if (order !== 0) { return order } return a[1] - b[1] }) return stabilizedThis.map((el) => el[0]) } const headCells = [ { id: 'name ', numeric: false, disablePadding: true, label: ' Name ', }, { id: ' likes ', numeric: true, disablePadding: false, label: ' Likes ', }, ] function EnhancedTableHead(props) { const { onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort, } = props const createSortHandler = (property) => (event) => { onRequestSort(event, property) } return ( <TableHead> <TableRow> {headCells.map((headCell) => ( <TableCell key={headCell.id} align="center" padding={headCell.disablePadding ? ' none ' : ' normal '} sortDirection={orderBy === headCell.id ? order : false} > <TableSortLabel direction={orderBy === headCell.id ? order : ' asc '} onClick={createSortHandler(headCell.id)} > {headCell.label} {orderBy === headCell.id ? ( <Box component="span" sx={visuallyHidden}> {order === ' desc ' ? ' sorted descending ' : ' sorted ascending '} </Box> ) : null} </TableSortLabel> </TableCell> ))} </TableRow> </TableHead> ) } EnhancedTableHead.propTypes = { numSelected: PropTypes.number.isRequired, onRequestSort: PropTypes.func.isRequired, onSelectAllClick: PropTypes.func.isRequired, order: PropTypes.oneOf([' asc ', ' desc ']).isRequired, orderBy: PropTypes.string.isRequired, rowCount: PropTypes.number.isRequired, } const EnhancedTableToolbar = (props) => { const { numSelected } = props return <Toolbar></Toolbar> } EnhancedTableToolbar.propTypes = { numSelected: PropTypes.number.isRequired, } function TableSorter() { const [order, setOrder] = React.useState(' asc ') const [orderBy, setOrderBy] = React.useState(' calories ') const [selected, setSelected] = React.useState([]) const [page, setPage] = React.useState(0) const [rowsPerPage, setRowsPerPage] = React.useState(5) const handleRequestSort = (event, property) => { const isAsc = orderBy === property && order === ' asc ' setOrder(isAsc ? ' desc ' : ' asc ') setOrderBy(property) } const handleSelectAllClick = (event) => { if (event.target.checked) { const newSelecteds = rows.map((n) => n.name) setSelected(newSelecteds) return } setSelected([]) } const handleClick = (event, name) => { const selectedIndex = selected.indexOf(name) let newSelected = [] if (selectedIndex === -1) { newSelected = newSelected.concat(selected, name) } else if (selectedIndex === 0) { newSelected = newSelected.concat(selected.slice(1)) } else if (selectedIndex === selected.length - 1) { newSelected = newSelected.concat(selected.slice(0, -1)) } else if (selectedIndex > 0) { newSelected = newSelected.concat( selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1), ) } setSelected(newSelected) } const isSelected = (name) => selected.indexOf(name) !== -1 return ( <Box sx={{ width: ' 100% ' }}> <Paper sx={{ mb: 2, px: 2 }}> <EnhancedTableToolbar numSelected={selected.length} /> <TableContainer> <Table aria-labelledby="tableTitle"> <EnhancedTableHead numSelected={selected.length} order={order} orderBy={orderBy} onSelectAllClick={handleSelectAllClick} onRequestSort={handleRequestSort} rowCount={rows.length} /> <TableBody> {/* if you don' t need to support IE11, you can replace the `stableSort` call with : rows.slice().sort(getComparator(order, orderBy)) */} {stableSort(rows, getComparator(order, orderBy)) .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) .map((row, index) => { const isItemSelected = isSelected(row.name) const labelId = `enhanced-table-checkbox-${index}` return ( <TableRow hover onClick={(event) => handleClick(event, row.name)} role= "checkbox" aria-checked={isItemSelected} tabIndex={-1} key={row.name} selected={isItemSelected} > <TableCell component= "th" id={labelId} scope= "row" padding= "none" align= "center" > {row.name} </TableCell> <TableCell align= "center" > {row.likes}</TableCell> </TableRow> ) })} </TableBody> </Table> </TableContainer> </Paper> </Box> ) } export default App |
Output:
Example 2: In the following example, we have set the active which will show the icon at the end.
App.js
import * as React from 'react' import PropTypes from 'prop-types' import { Box, Table, TableRow, TableCell, TableHead, TableContainer, TableBody, TableSortLabel, Paper, Toolbar, } from '@mui/material' import { visuallyHidden } from '@mui/utils' function App() { return ( <div className= "App" > <div className= "head" style={{ width: 'fit-content' , margin: 'auto' , }} > <h1 style={{ color: 'green' , }} > neveropen </h1> <strong> React MUI TableSortLabel API</strong> </div> <TableSorter /> </div> ) } function createData(name, likes) { return { name, likes, } } const rows = [ createData( 'C++' , 305), createData( 'Java' , 452), createData( 'Python' , 262), createData( 'React' , 159), createData( 'Rust' , 356), ] function descendingComparator(a, b, orderBy) { if (b[orderBy] < a[orderBy]) { return -1 } if (b[orderBy] > a[orderBy]) { return 1 } return 0 } function getComparator(order, orderBy) { return order === 'desc' ? (a, b) => descendingComparator(a, b, orderBy) : (a, b) => -descendingComparator(a, b, orderBy) } // This method is created for cross-browser // compatibility, if you don't need to support IE11, // you can use Array.prototype.sort() directly function stableSort(array, comparator) { const stabilizedThis = array.map((el, index) => [el, index]) stabilizedThis.sort((a, b) => { const order = comparator(a[0], b[0]) if (order !== 0) { return order } return a[1] - b[1] }) return stabilizedThis.map((el) => el[0]) } const headCells = [ { id: 'name ', numeric: false, disablePadding: true, label: ' Name ', }, { id: ' likes ', numeric: true, disablePadding: false, label: ' Likes ', }, ] function EnhancedTableHead(props) { const { onSelectAllClick, order, orderBy, numSelected, rowCount, onRequestSort, } = props const createSortHandler = (property) => (event) => { onRequestSort(event, property) } return ( <TableHead> <TableRow> {headCells.map((headCell) => ( <TableCell key={headCell.id} align="center" padding={headCell.disablePadding ? ' none ' : ' normal '} sortDirection={orderBy === headCell.id ? order : false} > <TableSortLabel active={orderBy === headCell.id} direction={orderBy === headCell.id ? order : ' asc '} onClick={createSortHandler(headCell.id)} > {headCell.label} {orderBy === headCell.id ? ( <Box component="span" sx={visuallyHidden}> {order === ' desc ' ? ' sorted descending ' : ' sorted ascending '} </Box> ) : null} </TableSortLabel> </TableCell> ))} </TableRow> </TableHead> ) } EnhancedTableHead.propTypes = { numSelected: PropTypes.number.isRequired, onRequestSort: PropTypes.func.isRequired, onSelectAllClick: PropTypes.func.isRequired, order: PropTypes.oneOf([' asc ', ' desc ']).isRequired, orderBy: PropTypes.string.isRequired, rowCount: PropTypes.number.isRequired, } const EnhancedTableToolbar = (props) => { const { numSelected } = props return <Toolbar></Toolbar> } EnhancedTableToolbar.propTypes = { numSelected: PropTypes.number.isRequired, } function TableSorter() { const [order, setOrder] = React.useState(' asc ') const [orderBy, setOrderBy] = React.useState(' calories ') const [selected, setSelected] = React.useState([]) const [page, setPage] = React.useState(0) const [rowsPerPage, setRowsPerPage] = React.useState(5) const handleRequestSort = (event, property) => { const isAsc = orderBy === property && order === ' asc ' setOrder(isAsc ? ' desc ' : ' asc ') setOrderBy(property) } const handleSelectAllClick = (event) => { if (event.target.checked) { const newSelecteds = rows.map((n) => n.name) setSelected(newSelecteds) return } setSelected([]) } const handleClick = (event, name) => { const selectedIndex = selected.indexOf(name) let newSelected = [] if (selectedIndex === -1) { newSelected = newSelected.concat(selected, name) } else if (selectedIndex === 0) { newSelected = newSelected.concat(selected.slice(1)) } else if (selectedIndex === selected.length - 1) { newSelected = newSelected.concat(selected.slice(0, -1)) } else if (selectedIndex > 0) { newSelected = newSelected.concat( selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1), ) } setSelected(newSelected) } const isSelected = (name) => selected.indexOf(name) !== -1 return ( <Box sx={{ width: ' 100% ' }}> <Paper sx={{ mb: 2, px: 2 }}> <EnhancedTableToolbar numSelected={selected.length} /> <TableContainer> <Table aria-labelledby="tableTitle"> <EnhancedTableHead numSelected={selected.length} order={order} orderBy={orderBy} onSelectAllClick={handleSelectAllClick} onRequestSort={handleRequestSort} rowCount={rows.length} /> <TableBody> {/* if you don' t need to support IE11, you can replace the `stableSort` call with : rows.slice().sort(getComparator(order, orderBy)) */} {stableSort(rows, getComparator(order, orderBy)) .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) .map((row, index) => { const isItemSelected = isSelected(row.name) const labelId = `enhanced-table-checkbox-${index}` return ( <TableRow hover onClick={(event) => handleClick(event, row.name)} role= "checkbox" aria-checked={isItemSelected} tabIndex={-1} key={row.name} selected={isItemSelected} > <TableCell component= "th" id={labelId} scope= "row" padding= "none" align= "center" > {row.name} </TableCell> <TableCell align= "center" > {row.likes}</TableCell> </TableRow> ) })} </TableBody> </Table> </TableContainer> </Paper> </Box> ) } export default App |
Output:
Reference: https://mui.com/material-ui/api/table-sort-label/