Material Table React Custom Row Rendering - reactjs

How to render custom nodes from data in Material Table react
( Ex: I want to show rows only with particular filed value>0)

If I understood your question correctly, you need to show a row in the table based on your condition. You can add that same condition while preparing the data.
I have attached a sandbox for rendering the same. I took a boolean value to display the row or not in the table.
Something like this.
<>
{row?.showValue && (
<TableRow
key={row.name}
sx={{ "&:last-child td, &:last-child th": { border: 0 } }}
>
<TableCell component="th" scope="row">
{row['property']}
</TableCell>
</TableRow>
)}
</>;

Related

Each child in a list should have a unique "key" prop in table React

I don't know where is the error I'm getting in the console, everything seems fine, does anyone have any idea what could be wrong?
Unique key error
<TableBody>
{announcements.map((announcement) => (
<TableRow
key={announcement.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell align="left">
<Box display='flex' alignItems='center'>
<Avatar src={announcement.photoUrl} alt={announcement.announcementTitle}
style={{ height: 50, width: 50, marginRight: 20 }} />
<span>{announcement.announcementTitle}</span>
</Box>
</TableCell>
<TableCell align="right">
<Button onClick={() => handleSelectAnnouncement(announcement)} startIcon={<Edit />} />
<Button startIcon={<Delete />} color='error' />
</TableCell>
</TableRow>
))}
</TableBody>
After changing to key={index} I get this error, but I still don't know what is wrong. There are only 6 ID fields in the database, and it can't be duplicated anywhere.
warning after update key
Below is a link to the repository because there is quite a lot of code.
Last commit on GitHub
Most probably here you have a duplicate announcement.id values you can fix it like this use the index as key it will be always unique :
{announcements.map((announcement,index) => (
<TableRow
key={index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }} > ... </TableRow>
You are likely passing some undefined or null value to the key prop. Check whether every announcement object has an string id property.
However, it's not recommended to use the array index as unique key when the array comes from a database (or will change at some point).

How to make the Material UI's table header sticky in relation to an outer scroll?

I have a page that uses Material UI's table and I need to get the sticky header working when the entire page is scrolled, since the table must be allowed to take as much vertical space as it needs, like in this pure HTML+CSS example.
I couldn't manage to do this with MUI's table, though. How can it be achieved?
demo
Set overflowX to initial on TableContainer
...
<TableContainer style={{ overflowX: "initial" }}>
...
Read more on this link
Related issue
Wanted mui table with sticky header & rotated to -45 degree angle
Below din't work:
Wasted 3 hours to make stickyHeader work
<Table stickyHeader ...
Below worked:
Apply head1 CSS for TableHead:
Apply rotatedContent1 CSS for TableCell's child (NOTE: child):
Full code is something like below:
const TableStyles = theme => ({
head1: {
zIndex: 3,
position: 'sticky',
top: '0px',
},
rotatedContent1: {
transform: 'rotate(270deg)',
}
})
const Component1 = ({ classes }) => {
return (
<React.Fragment>
<Table>
<TableHead className={classes.head1}>
<TableCell>
<div className={classes.rotatedContent1}> header value </div>
</TableCell>
</TableHead>
<TableBody>
<TableRow>
<TableCell> value </TableCell>
</TableRow>
</TableBody>
</Table>
</React.Fragment>
)
}
export default withStyles(TableStyles)(Component1)

how to do bind data with material-ui table and also pagination

I have facing an issue with binding my data with the material-UI table
(1) first thing it is just showing the product name and when I am trying to add product price so it is now binding there
(2) also I have done pagination on my server-side but when i change the page of my table it is just showing the first 5 rows
in this image, you can easily see that just names are showing on the table, and in the console, there are two arrays showing, the first one occurred when the page was loaded and the second one occurred when I change my pagination, check the pagination in the page.
here is my table code
products.map((row) => (
<TableRow key={row.name}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell style={{ width: 160 }} align="right">
{row.calories}
</TableCell>
<TableCell style={{ width: 160 }} align="right">
{row.fat}
</TableCell>
</TableRow>
))}
here i am fetching data
const dispatch = useDispatch();
const {loading, products, error, productCount} = useSelector(state => state.products);
useEffect(()=>{
dispatch(getProducts());
},[dispatch])
I am also attaching the material-UI link here which I am using, I just simple copied and paste code the
on the page of material-UI, you can see Custom pagination actions
https://mui.com/components/tables/#main-content
For Pagination, you can use DataGrid in MUI,
First, you have to define a constant for columns naming like below then use the MUI DataGrid
const columns = [
{ field: "name", headerName: "Name" },
{ field: "calories", headerName: "Calories" },
{ field: "fat", headerName: "Fat" },
]
<DataGrid
rows={products}
columns={columns}
pageSize={5}
rowsPerPageOptions={[5, 10, 15]}
checkboxSelection={false}
/>
Here Products is the list you are providing the page to render.
And you have to handle the listing rows pagination by Top, Skip Strategy

How to make TableCell with full Table width with MaterialUI in React?

I got a table, which is looking like this:
import { Typography, Table, TableHead, TableRow, TableCell, TableBody } from '#material-ui/core';
const Example = () => {
return (
<>
<Table>
<TableHead>
<TableRow>
<TableCell align="center"><Typography> 1 </Typography></TableCell>
<TableCell align="center"><Typography> Some </Typography></TableCell>
<TableCell align="center"><Typography> Some</Typography></TableCell>
<TableCell align="center"><Typography> Some </Typography></TableCell>
<TableCell align="center"><Typography> Some </Typography></TableCell>
</TableRow>
</TableHead>
<TableBody>
{
// Here I'm loading some async data
// Meanwhile it's fetching I want to display some loading indicator
}
</TableBody>
</Table>
</>
)
}
And in the TableBody before I display a normal TableRows with data I want to display to users loading indicator that is in the middle of the table. So basically I need one TableCell inside this table that is taking all the columns width, so then I will be able to center my indicator.
How can I achieve that using MaterialUI Components and their API to make my table look like this:
You can expand the cell which you want to include the loading indicator like the following.
Table DOM structure should be considered.
<Table>
<TableHead>
{
!isLoaded
? <TableRow>
<TableCell
colSpan={5} // it seems each line has 5 table cells
align="center"
>
<LoadIndicator />
</TableCell>
: <TableBody>
...
}
Using component props.
<Table component="div">
<TableHead component="div" />
{
!isLoaded
? <LoadIndicator>
: <TableBody component="div">
...
}
...

ReactJS Table conditional styling based on previous value

I have a React JS app using Material-UI Table component that looks like this:
I need to change the style of the border between the last row of the same date and the first row of another date like between Date A and Date B like this:
My code to create the table is just a normal map :
<TableCell>
<Typography style={{ fontSize: 16 }}>{new Date(row.date).toLocaleDateString().slice(0, 10)}</Typography>
</TableCell>
<TableCell><Typography noWrap={true} style={{ fontSize: 16 }}>{row.user}</Typography></TableCell>
<TableCell><Typography style={{ fontSize: 16 }}>{row.duration}h</Typography></TableCell>
<TableCell><Typography style={{ fontSize: 16 }}>{row.description}</Typography></TableCell>
<TableCell style={{ width: 35 }} align="left">
<IconButton
className={classes.iconButton}
style={{ marginRight: 3 }}
onClick={() => openWorklogModalForEdit(row.id, row.date, row.duration, row.description, row.project_id, row.user_id, row.project, row.clientName)}>
<EditIcon className={classes.actionsButtonIcon} />
</IconButton>
</TableCell>
<TableCell style={{ width: 65 }} align="right" >
<IconButton
className={classes.iconButton}
onClick={() => deleteWorklog(row.id)}>
<DeleteIcon className={classes.actionsButtonIcon} />
</IconButton>
</TableCell>
</TableRow>
Thank you for your time!
You can add class for first table row of different date when using .map. Please refer to this code snippet for a simple demo.
Thoughts:
As you're using map to construct a table from an array, the syntax is
let newArray = arr.map(callback(currentValue[, index[, array]]) {
// return element for newArray, after executing something
}[, thisArg]);
docs: link
Then in the map callback body, you have access to current value and index. Then you can check whether the current item is the first of a new 'group', or a new date. If true, you can add a custom class to this row (as the demo is doing).
Then you can use css to add the border, so that you can achieve 'conditional styling based on previous value'.
If you can change the styling by adding or deleting class on some element this can easily be done.
<td className={shouldBeBlack ? 'black' : 'orange'} ></td>
so like depending on value of shouldBeBlack you can set css property of the table data or any element. Just depends how u r styling.
If there is some prop you can pass to the material ui element then same c=kind of ternary equation can be made for the same.
By apply mapping, you can add check like this
rows.map((row,index)=>{
if(index !== 0)?
<td className={row.date === rows[index-1].date? 'blackLine' : 'orangeLine'} </td>
:
<td className='black'} ></td>
})

Resources