Introduction
As a web developer, I often find myself struggling to create functional and visually appealing tables for my web applications. When I discovered Material UI V5, I was intrigued by the promise of a streamlined and customizable table component. In this article, I’ll delve into the world of Material UI V5 Tables and share my insights, tips, and tricks for getting the most out of this powerful tool.
Let’s start with the basics. To get started with Material UI V5 Tables, you’ll need to install and set up the Material UI library. This can be done using npm, yarn, or a direct download. Once you have Material UI set up, you’re ready to create your first table.
import { Table, TableBody, TableCell, TableContainer,
TableHead, TableRow, Paper } from '@mui/material';
function BasicTable() {
return (
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>John</TableCell>
<TableCell>Doe</TableCell>
<TableCell>[email protected]</TableCell>
</TableRow>
<TableRow>
<TableCell>Jane</TableCell>
<TableCell>Doe</TableCell>
<TableCell>[email protected]</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
);
}
Here we have a basic table component with two rows of data, each containing a first name, last name and email address. The TableContainer component is used to provide the paper background for the table, while the TableHead and TableBody components provide the structure for the headers and data respectively. The TableCell component is used to display individual cells within the table, while the TableRow component is used for grouping cells into rows.
Of course, this is just a starting point. Material UI V5 Tables are highly customizable, and there are a number of ways to style and enhance the default table. Let’s explore some of these options in more detail.
Customizing Material UI V5 Tables
Styling the Table
One of the great advantages of using Material UI V5 Tables is the ease with which you can style them to fit seamlessly into your application’s design. Here’s an example of how to add some custom styling to our previous table:
import { makeStyles } from '@mui/styles';
const useStyles = makeStyles({
table: {
minWidth: 650,
'& th': {
fontWeight: 'bold',
backgroundColor: '#f2f2f2',
color: '#090909'
},
'& tbody tr:nth-of-type(even)': {
backgroundColor: '#f2f2f2'
}
},
});
function StyledTable() {
const classes = useStyles();
return (
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>John</TableCell>
<TableCell>Doe</TableCell>
<TableCell>[email protected]</TableCell>
</TableRow>
<TableRow>
<TableCell>Jane</TableCell>
<TableCell>Doe</TableCell>
<TableCell>[email protected]</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
);
}
Notice the makeStyles hook and the associated table style object. We then add the class classes.table
to the Table component to apply our custom styling. In this example, we’ve set a minimum width for the table, added a background color to the header row, and alternating background colors to rows to improve readability.
Adding Pagination
Another useful feature of Material UI V5 Tables is the built-in ability to paginate data. Here’s how to add pagination to our previous example:
import { useState } from 'react';
import { TablePagination } from '@mui/material';
function PaginatedTable() {
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
return (
<div>
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => (
<TableRow key={row.id}>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={data.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</div>
);
}
Here we’ve added a TablePagination component below the table to control the number of rows displayed per page and handle pagination. Notice the useState hook used to keep track of the current page and number of rows per page. The handleChangePage
and handleChangeRowsPerPage
functions are called when the user interacts with the pagination controls. We’ve also changed the TableBody component to display a slice of data based on the current page and number of rows per page.
Filtering and Sorting the Table
Filtering and sorting data is another powerful feature provided by Material UI V5 Tables. Here’s an example of how to add filtering and sorting to our previous example:
import { useState } from 'react';
import { TableHead, TableRow, TableSortLabel } from '@mui/material';
const createData = (id, firstName, lastName, email) => {
return { id, firstName, lastName, email };
};
const rows = [
createData(1, 'John', 'Doe', '[email protected]'),
createData(2, 'Jane', 'Doe', '[email protected]'),
createData(3, 'Bruce', 'Wayne', '[email protected]'),
createData(4, 'Tony', 'Stark', '[email protected]'),
createData(5, 'Diana', 'Prince', '[email protected]'),
createData(6, 'Clark', 'Kent', '[email protected]')
];
function EnhancedTable() {
const [order, setOrder] = useState('asc');
const [orderBy, setOrderBy] = useState('firstName');
const handleRequestSort = (event, property) => {
const isAsc = orderBy === property && order === 'asc';
setOrder(isAsc ? 'desc' : 'asc');
setOrderBy(property);
};
return (
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>
<TableSortLabel
active={orderBy === 'firstName'}
direction={orderBy === 'firstName' ? order : 'asc'}
onClick={(event) => handleRequestSort(event, 'firstName')}
>
First Name
</TableSortLabel>
</TableCell>
<TableCell>
<TableSortLabel
active={orderBy === 'lastName'}
direction={orderBy === 'lastName' ? order : 'asc'}
onClick={(event) => handleRequestSort(event, 'lastName')}
>
Last Name
</TableSortLabel>
</TableCell>
<TableCell>
<TableSortLabel
active={orderBy === 'email'}
direction={orderBy === 'email' ? order : 'asc'}
onClick={(event) => handleRequestSort(event, 'email')}
>
Email
</TableSortLabel>
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{stableSort(rows, getComparator(order, orderBy)).map((row) => (
<TableRow key={row.id}>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
We’ve added a createData
function to create our data rows, and a stableSort
function to sort the data. The handleRequestSort
function is called when a user clicks on a TableSortLabel component to sort the data by the clicked column. Notice how we use the useState hooks to maintain the current sort order and sorted column.
Advanced Functionality of Material UI V5 Tables
Handling Click Events
Material UI V5 Tables provide a way to handle click events for rows, cells and headers. Here’s an example of how to handle a click event for a row:
import { TableRow } from '@mui/material';
function ClickableRowTable() {
const handleClick = (event, id) => {
console.log(`Row with id ${id} clicked!`);
};
return (
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((row) => (
<TableRow key={row.id} hover onClick={(event) => handleClick(event, row.id)}>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
Here we’ve added a handleClick
function that logs a message containing the id of the clicked row. We’ve also added the hover
prop to the TableRow component to highlight the row on hover.
Implementing Row Selection
You can also implement row selection within Material UI V5 Tables, using the TableBodyProps and TableRowProps components. Here’s an example of how to select rows:
import { Checkbox, TableBodyProps } from '@mui/material';
function SelectableRowsTable() {
const [selected, setSelected] = useState([]);
const handleSelectAllClick = (event) => {
if (event.target.checked) {
const newSelected = data.map((n) => n.id);
setSelected(newSelected);
return;
}
setSelected([]);
};
const handleClick = (event, id) => {
const selectedIndex = selected.indexOf(id);
let newSelected = [];
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id);
} 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 = (id) => selected.indexOf(id) !== -1;
return (
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell padding="checkbox">
<Checkbox
indeterminate={selected.length > 0 && selected.length < data.length}
checked={selected.length === data.length}
onChange={handleSelectAllClick}
inputProps={{ 'aria-label': 'select all desserts' }}
/>
</TableCell>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody component={TableBodyProps}>
{data.map((row) => {
const isItemSelected = isSelected(row.id);
const labelId = `enhanced-table-checkbox-${row.id}`;
return (
<TableRow
hover
onClick={(event) => handleClick(event, row.id)}
role="checkbox"
aria-checked={isItemSelected}
tabIndex={-1}
key={row.id}
selected={isItemSelected}
{...TableRowProps}
>
<TableCell padding="checkbox">
<Checkbox
checked={isItemSelected}
inputProps={{ 'aria-labelledby': labelId }}
/>
</TableCell>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.email}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
);
}
Here, the selected
state stores an array of ids for the currently selected rows. The handleSelectAllClick
function is called when the user clicks the “Select All” checkbox, which either selects all rows or clears the selection. The handleClick
function is called when the user clicks on a row, and it either selects or deselects the row depending on its current state. The isSelected
function checks whether a particular row is selected or not. Finally, we’ve added the selected
and TableRowProps
props to the TableRow component to visually highlight the selected rows.
Implementing Custom Cell Rendering
Material UI V5 Tables also provide the ability to customize the rendering of table cells, by using the TableCell
component’s component
prop.
function CustomCellTable() {
const data = [
{ id: 1, firstName: 'John', lastName: 'Doe', email: '[email protected]', phone: '123-456-7890' },
{ id: 2, firstName: 'Jane', lastName: 'Doe', email: '[email protected]', phone: '234-567-8901' },
{ id: 3, firstName: 'Clark', lastName: 'Kent', email: '[email protected]', phone: '345-678-9012' },
{ id: 4, firstName: 'Diana', lastName: 'Prince', email: '[email protected]', phone: '456-789-0123' },
{ id: 5, firstName: 'Bruce', lastName: 'Wayne', email: '[email protected]', phone: '567-890-1234' },
{ id: 6, firstName: 'Tony', lastName: 'Stark', email: '[email protected]', phone: '678-901-2345' }
];
const renderCell = (value, rowIndex, columnIndex) => {
if (columnIndex === 4) {
return <a href={`tel:${value}`}>{value}</a>;
}
return value;
};
return (
<TableContainer component={Paper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email</TableCell>
<TableCell>Phone</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data.map((row) => (
<TableRow key={row.id}>
<TableCell>{row.firstName}</TableCell>
<TableCell>{row.lastName}</TableCell>
<TableCell>{row.email}</TableCell>
<TableCell>
<TableCell component="th" scope="row">
{renderCell(row.phone, row.id, 4)}
</TableCell>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
In this example, we’ve defined a data
array, each object representing a row of data. We’ve also defined a renderCell
function that takes in a cell value, row index, and column index, and returns the appropriate JSX to render the cell. Here, we’re rendering a hyperlink for cell values in the “Phone” column.
Conclusion
Material UI V5 Tables provide a powerful and flexible way to display data in a web application. They offer sophisticated sorting, filtering, and pagination functionality that can be customized to meet specific requirements. Additionally, by leveraging the component-based architecture, developers can build complex and accessible user interfaces quickly and maintain them efficiently. With a solid understanding of the fundamentals, developers can build rich, responsive, and accessible data tables with Material UI V5 Tables.
Use Material UI V5 With Typescript
Introduction Hello everyone! In this article, we are going to talk about Material UI V5 with Typescript. If you are a React developer, you must have heard of Material UI. It is one of the most popular React UI component libraries out there. On the other hand, Typescript is a superset of JavaScript that provides […]
Select Component In Material UI V5
Hey there, fellow developers! In this article, we’re going to dive into the world of Material UI and take a closer look at one of its most essential components – the Select Component. I’m excited to share with you how to implement and customize this component in Material UI V5. So, let’s get started! Introduction […]
Backdrops In Material UI V5
As a developer, I’m always on the lookout for tools and frameworks that can make my job easier. That’s why I love Material UI. This popular React UI component library provides a wealth of customizable and responsive components that can be easily integrated into any project. One useful component of Material UI is the backdrop […]
Autocomplete In Material UI V5
Introduction Hello everyone, today I am going to talk about one of the most useful components in Material UI V5 – Autocomplete. Material UI is a popular React UI framework that provides a wide range of pre-designed components to make the development of complex user interfaces simpler. Autocomplete is an intuitive component that provides suggestions […]
Toggle Buttons In Material UI V5
As a developer, I’ll be the first to admit that sometimes I find myself perplexed by certain UI design choices. As someone who spends a lot of time within the realm of code, I focus more on functionality and less on design. But the more I learn about UI design, the more I realize the […]
Text Fields In Material UI V5
I. Introduction As the popularity of Material UI as a user interface kit continues to rise, developers have found themselves working with text fields more often. Text fields are one of the most essential elements in any form and Material UI has made using them fun and straightforward.This article seeks to highlight the features, use, […]