How can you style the header of a MUI table like height and width?
<TableHead >
<TableRow >
<TableCell hover>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
I tried passing
sx={{ height:'20px' }}
but the height is fixed
You can achieve that by using sx on the TableHead component:
<TableHead sx={{height:"150px"}}>
<TableRow >
<TableCell hover>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat (g)</TableCell>
<TableCell align="right">Carbs (g)</TableCell>
<TableCell align="right">Protein (g)</TableCell>
</TableRow>
</TableHead>
To customize the styling of the TableHead you need to target the MuiTableCell-head class of the Table.
One important thing to notice, Mui TableHead height is not coming from the height property, It is coming from line-height. Please check the example below:
import { Table, TableHead, TableBody } from '#mui/material'
<Table sx={{ '& .MuiTableCell-head':{ lineHeight: 20, color: 'red' } }}>
<TableHead>
</TableHead>
<TableBody>
</TableBody>
</Table>
I have this materia-ui table. Every time I'll click the button to expand the row1, it will also expand the second row. How can I fix this where only that specific row will expand?
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow hover>
<TableCell>Title</TableCell>
<TableCell>Created Date</TableCell>
</TableRow>
</TableHead>
<TableBody>
{data &&
data((index) => (
<TableRow hover>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? (
<KeyboardArrowUpIcon />
) : (
<KeyboardArrowDownIcon />
)}
</IconButton>
</TableCell>
<TableCell component="th" scope="row">
{index.title}
</TableCell>
<TableCell component="th" scope="row">
{new Date(
index.createdDate.seconds * 1000
).toDateString()}
</TableCell>
<TableCell colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
{index.text}
</Collapse>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
Wrap TableRow in a component
const Row = ({item}) => {
const [open, setOpen] = useState(false);
return <TableRow>...</TableRow>
}
<TableBody>
{data.map((item, index) => (
<Row key={index} item={item} />
))}
</TableBody>
I am trying to use the material UI minimized table to create a dashboard https://material-ui.com/pt/components/tables/
I ran into an issue that I'm stuck with for the last 5 hours. I could successfully render the data from my database to display in the table. However, when I retrieve the data using the map function, all is displayed in one single row x5.
Picture: Front-end view
I'm trying to display the name and data in different rows and not "Sue Flavio John Doe rajid" because each is a different object.
I'd appreciate some help to understand where is my logical mistake.
function EmployeeList() {
const [employeeList, setEmployeeList] = useState([]);
console.log(employeeList);
useEffect(() => {
Axios.get("http://localhost:4000/vacations_cs_read").then((response) => {
setEmployeeList(response.data);
});
}, []);
const Row = () => {
const [open, setOpen] = React.useState(false);
const classes = useRowStyles();
return (
<React.Fragment>
<TableRow className={classes.root}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
<TableCell component="th" scope="row">
{employeeList.map((val, key) => {
return <td>{val.employeeName}</td>;
})}
</TableCell>
<TableCell align="left">
{employeeList.map((val, key) => {
const day = new Date(val.employeeStartDay).toLocaleDateString(
"pt-BR"
);
return <td>{day}</td>;
})}
</TableCell>
<TableCell align="left">
<p>-</p>
</TableCell>
<TableCell align="left">
<p>-</p>
</TableCell>
<TableCell align="left">
<p>-</p>
</TableCell>
</TableRow>
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>From</TableCell>
<TableCell>To</TableCell>
<TableCell align="left">Days</TableCell>
<TableCell align="left">Paid</TableCell>
</TableRow>
</TableHead>
<TableBody>
{/* {row.history.map(() => (
<TableRow>
<TableCell component="th" scope="row"></TableCell>
<TableCell></TableCell>
<TableCell align="left"></TableCell>
<TableCell align="left"></TableCell>
</TableRow>
))} */}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
};
Row.propTypes = {
row: PropTypes.shape({
name: PropTypes.string,
startDate: PropTypes.string,
shift: PropTypes.string,
daysReceived: PropTypes.number,
daysUsed: PropTypes.number,
daysLeft: PropTypes.number,
history: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.number,
customerId: PropTypes.string,
date: PropTypes.string,
})
),
}),
};
return (
<div>
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableHead>
<TableRow>
<TableCell />
<TableCell>Name</TableCell>
<TableCell align="left">Employment Date</TableCell>
<TableCell align="left">Days received</TableCell>
<TableCell align="left">Days used</TableCell>
<TableCell align="left">Days left</TableCell>
</TableRow>
</TableHead>
<TableBody>
{employeeList.map((val, key) => (
<Row />
))}
</TableBody>
</Table>
</TableContainer>
</div>
);
}
Well, you are not giving the data to each row in the map call where you iterate over the employees. And then, instead you iterate of the whole thing again in each cell..
This should work:
const Row = ({val}) => {
const [open, setOpen] = React.useState(false);
const classes = useRowStyles();
return (
<React.Fragment>
<TableRow className={classes.root}>
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
<TableCell component="th" scope="row">
{val.employeeName}
</TableCell>
<TableCell align="left">
{(new Date(val.employeeStartDay)).toLocaleDateString("pt-BR")}
</TableCell>
<TableCell align="left">
<p>-</p>
</TableCell>
<TableCell align="left">
<p>-</p>
</TableCell>
<TableCell align="left">
<p>-</p>
</TableCell>
</TableRow>
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box margin={1}>
<Typography variant="h6" gutterBottom component="div">
History
</Typography>
<Table size="small" aria-label="purchases">
<TableHead>
<TableRow>
<TableCell>From</TableCell>
<TableCell>To</TableCell>
<TableCell align="left">Days</TableCell>
<TableCell align="left">Paid</TableCell>
</TableRow>
</TableHead>
<TableBody>
{/* {row.history.map(() => (
<TableRow>
<TableCell component="th" scope="row"></TableCell>
<TableCell></TableCell>
<TableCell align="left"></TableCell>
<TableCell align="left"></TableCell>
</TableRow>
))} */}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</React.Fragment>
);
};
Row.propTypes = {
row: PropTypes.shape({
name: PropTypes.string,
startDate: PropTypes.string,
shift: PropTypes.string,
daysReceived: PropTypes.number,
daysUsed: PropTypes.number,
daysLeft: PropTypes.number,
history: PropTypes.arrayOf(
PropTypes.shape({
amount: PropTypes.number,
customerId: PropTypes.string,
date: PropTypes.string,
})
),
}),
};
return (
<div>
<TableContainer component={Paper}>
<Table aria-label="collapsible table">
<TableHead>
<TableRow>
<TableCell />
<TableCell>Name</TableCell>
<TableCell align="left">Employment Date</TableCell>
<TableCell align="left">Days received</TableCell>
<TableCell align="left">Days used</TableCell>
<TableCell align="left">Days left</TableCell>
</TableRow>
</TableHead>
<TableBody>
{employeeList.map((val, key) => <Row val={val} key={key}/>)}
</TableBody>
</Table>
</TableContainer>
</div>
);
The structure you should be using should look something like this:
function Row(props) {
// you can access the employee object as `props.employee`
...
}
...
{employeeList.map((val, key) => <Row key={key} employee={val} />}
Each time you call the row function, it gives you a new row. For it to know what data should be in that row, you should be passing that data as a prop, instead of using the state. The flow of data would therefore be that the render method has a list of employees, and it calls the row builder function once with each of them, which gives back a list of rows to render.
I want to display some data in a table this is my JSX code:
const StudentsTable = (props) => {
const classes = useStyles();
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell>NR.</TableCell>
<TableCell align="right">NUME</TableCell>
<TableCell align="right">E-MAIL</TableCell>
<TableCell align="right">NR.TELEFON</TableCell>
<TableCell align="right">CLASA</TableCell>
<TableCell align="right">ACTIUNI</TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.students.length > 0 ? (
props.students.map((student, i) => (
<TableRow key={student.studentName}>
<TableCell component="th" scope="row">
{i + 1}
</TableCell>
<TableCell align="right">{student.studentName}</TableCell>
<TableCell align="right">{student.studentEmail}</TableCell>
<TableCell align="right">{student.studentPhone}</TableCell>
<TableCell align="right">{student.clasa}</TableCell>
<TableCell align="center" className={classes.actionsCell}>
<BootstrapButton variant="primary" size="sm">
EDITARE
</BootstrapButton>
<BootstrapButton
variant="danger"
size="sm"
onClick={() => props.deleteStudent(student.studentName)}
>
STERGERE
</BootstrapButton>
</TableCell>
</TableRow>
))
) : (
<Typography variant="h5">
NU EXISTA ELEVI ADAUGATI.{"\n"} PUTETI ADAUGA APASAND PE BUTONUL
"ADAUGA ELEVI"
</Typography>
)}
</TableBody>
</Table>
</TableContainer>
);
};
when the props.students it's an empty array I want to return a single full-width row with this message: NU EXISTA ELEVI ADAUGATI.{"\n"} PUTETI ADAUGA APASAND PE BUTONUL "ADAUGA ELEVI" but in my app, the table looks something like this:
how to fix it?
In the place where you want to render a full row
use
<TableRow><TableCell colSpan={6}>"your message"</TableCell></TableRow>
So I am trying to create a table with material-ui where rows of w1 and w2 are merged vertically, but I can't seem to find a solution. Using rowSpan when hardcoding table manually works just fine, but when I use it inside map function it creates 4 columns with merged rows of the same element. I need to map data because there is going to be lots of rows in that table and hardcoding all rows is not reasonable.
Any type of suggestion to resolve this?
<TableBody>
{data.data.map((row, i) => (
<TableRow key={row.i}>
<TableCell className={classes.fontEditable} component="th" scope="row">
{row.x1}
</TableCell>
<TableCell className={classes.fontEditable} align="right">
{row.x2}
</TableCell>
<TableCell rowSpan={4} className={classes.fontEditable} align="right">
{row.w1}
</TableCell>
<TableCell rowSpan={4} className={classes.fontEditable} align="right">
{row.w2}
</TableCell>
<TableCell className={classes.font} align="right">
{row.t}
</TableCell>
</TableRow>
))}
</TableBody>
Expected outcome
Actual outcome
problem:
it creates the w1 and w2 cell in each row because of the map function
solution:
you can do an if condition for the w1 and w2 print for the first only as the following
<TableBody>
{data.data.map((row, i) => (
<TableRow key={row.i}>
<TableCell className={classes.fontEditable} component="th" scope="row">
{row.x1}
</TableCell>
<TableCell className={classes.fontEditable} align="right">
{row.x2}
</TableCell>
{i === 0?
<TableCell rowSpan={4} className={classes.fontEditable} align="right">
{row.w1}
</TableCell>
<TableCell rowSpan={4} className={classes.fontEditable} align="right">
{row.w2}
</TableCell>
:null}
<TableCell className={classes.font} align="right">
{row.t}
</TableCell>
</TableRow>
))}