I am trying to create two parallel tables that stick to each other on the same row. However, the second table is always stacked under the first table. The only idea I could think of is using Grid Item to determine the column span of each table, but I have no idea how to implement it.
Can you use Grid Container over the TableContainer?
const TableCellStyle = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
color: theme.palette.text.dark,
backgroundColor: theme.palette.success.light,
},
[`&.${tableCellClasses.body}`]: {
fontSize: 12,
}
}))
const TableRowStyle = styled(TableRow)(({ theme }) => ({
'&:nth-of-type(odd)': {
backgroundColor: theme.palette.action.hover,
},
'&:last-child td, &:last-child th': {
border: 0,
}
}))
function DataTable() {
return (
//first table
<TableContainer
component={Paper}
sx={{
width:'max-content',
marginLeft: 'auto',
marginRight: 'auto'
}}
>
<Table sx={{ minWidth: 400 }}>
<TableHead>
<TableRow>
<TableCellStyle>Position</TableCellStyle>
<TableCellStyle align="right">Defect Type by AI</TableCellStyle>
<TableCellStyle align="right">Tool Decision by AI</TableCellStyle>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRowStyle key={row.name}>
<TableCellStyle component="th" scope="row">
{row.name}
</TableCellStyle>
<TableCellStyle align="right">{row.Column1}</TableCellStyle>
<TableCellStyle align="right">{row.Column2}</TableCellStyle>
</TableRowStyle>
))}
</TableBody>
//second table
</Table>
<Table sx={{ minWidth: 400 }}>
<TableHead>
<TableRow>
<TableCellStyle>Position</TableCellStyle>
<TableCellStyle align="right">Defect Type by AI</TableCellStyle>
<TableCellStyle align="right">Tool Decision by AI</TableCellStyle>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRowStyle key={row.name}>
<TableCellStyle component="th" scope="row">
{row.name}
</TableCellStyle>
<TableCellStyle align="right">{row.Column1}</TableCellStyle>
<TableCellStyle align="right">{row.Column2}</TableCellStyle>
</TableRowStyle>
))}
</TableBody>
</Table>
</TableContainer>
);
}
Related
My table looks as such:
<TableContainer component={Paper} style={{height: "40vh", width: "90vh"}}>
<Table size="small" sx={{ minWidth: 200 }}>
<TableHead>
<TableRow>
<TableCell align="center" width="90"></TableCell>
{consequences_description.map((description) => (
<TableCell align="center" width="90">{description}</TableCell>
)
)}
</TableRow>
</TableHead>
<TableBody>
{risk_matrix.map((row, row_index) => (
<TableRow
key={row_index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{likelyhood_description[row_index]}
</TableCell>
{row.map( (column, column_index) => (
<TableCell align="center">
<ToggleButton
risk={column}
row_index={row_index}
column_index={column_index}
/>
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
The button inside the table is called <ToggleButton/> and it looks as such:
<ThemeProvider theme={filtersTheme}>
<Button variant="contained" color={handleColor()} onClick={console.log("Clicked")} >{risk}</Button>
</ThemeProvider>
As soon as the table renders, the console shows "Clicked", meaning the onClick function gets called for the button as soon as it renders inside the table for some reason, but I am not able to click it and fire the onClick function. Is there a way to do this?
Try to call the onClick function like this:
onClick={() => { console.log('Clicked');
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'm trying to make a table with Material UI in React like that:
Here is my code:
return (
<>
<div className="main-wrapper">
<TableContainer component={Paper}>
<Table style={{ minWidth: '650px' }} aria-label="caption table">
<caption>Test</caption>
<TableHead>
<TableRow>
<TableCell align="left" colSpan={1}>
Something else
</TableCell>
<TableRow align="center">
{daysMaps.map(day => (
<TableCell align="center" colSpan={90}>
{day}
</TableCell>
))}
</TableRow>
<TableRow align="center">
{daysMaps.map(() => {
{shifts.map(shift => {
<TableCell align="center">
{shift}
</TableCell>
})}
})}
</TableRow>
</TableRow>
</TableHead>
</Table>
</TableContainer>
</div>
</>
);
I just write the Table Head codes here.
These are the problems:
The shifts(morning, noon, night) doesn't appear on the page
A warning is shown on the console: Warning: validateDOMNesting(...): <tr> cannot appear as a child of <tr>.
How can I fix this problem and make a correct table?
You somehow mixed up the code and forgot the return statements:
<TableRow align="center">
{daysMaps.map(() => {
return shifts.map(shift => {
return <TableCell align="center">{shift}</TableCell>;
});
})}
</TableRow>
Alternatively, exchange the curly braces with round ones, then you can omit the return statement. I made a small codepen for you.
The warning seems to be related to the way material-ui renders the table.
I suspect you can't put TableRow inside a TableRow tag.
You'll need to use rowpspan somewhere. This is a guess, but perhaps like this:
return (
<>
<div className="main-wrapper">
<TableContainer component={Paper}>
<Table style={{ minWidth: '650px' }} aria-label="caption table">
<caption>Test</caption>
<TableHead>
<TableRow>
<TableCell align="left" colSpan={1} rowSpan="2">
Something else
</TableCell>
{daysMaps.map( (day, i) => (
<TableCell key={i} align="center" colSpan={3}>
{day}
</TableCell>
))}
</TableRow>
<TableRow>
{daysMaps.map(() => {
{shifts.map( (shift,i) => (
<TableCell key={i} align="center">
{shift}
</TableCell>
))}
})}
</TableRow>
</TableHead>
</Table>
</TableContainer>
</div>
</>
);
I've added key attributes in for you. You'll get an error without those,
this error means you cannot put a <tr> tag as a child of <tr> nor <td> as a child of <td>
change your code to this
<TableHead>
<TableRow>
<TableCell align="left" colSpan={1}>
Something else
</TableCell>
<TableCell align="center">
{daysMaps.map(day => (
<span style={{textAlign:"center"}}>
{day}
</span>
))}
</TableCell>
<TableCell align="center">
{daysMaps.map(() => { {shifts.map(shift => {
<span style={{textAlign:"center"}}>
{shift}
</span>
})} })}
</TableCell>
</TableRow>
</TableHead>
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>