Nested Material UI Dialog with Table not rendering - javascript

I have a component that renders a fullscreened <Dialog> with a <Table>.
Every row in this <Table> contains a <TableCell>, which contains a <Button> component.
When pressed, another, not fullscreened <Dialog> containing a <Table> should pop up and show what the object in the main <Table> contains.
Something like this:
---Basket---Total---Products----Date-----
-------A---------3------------[1]------someDate-- // [1] being the button
onClick() of [1] triggers the smaller <Dialog>
---Name---Price---Quantity---
----Prod-------3----------1------- // Nested <Dialog>
Now, I have a method that just parses the date I get from the backend into the Date column in the main <Table>.
Funnily, if I press the <Button> for the second, smaller <Dialog>, the method gets called again, everything freezes for 5 seconds and a bunch of windows pop up over each other.
I have my open variable in the state, so I thought that the whole thing gets rerenderer when I toggle it. Which would make sense.
I tried using <Modal> which would actually be a better option, but it just crashes Chrome. Screen becomes black with parallel lines across.
So, basically, I'm doing two loops in the <Dialog> component.
Here's the code using <Dialog>:
<Dialog
open={this.props.loadBasketsWindowOpen}
transition={Transition}
keepMounted
onClose={this.handleClose}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
fullScreen
>
<DialogTitle id="alert-dialog-slide-title">
<p style={centerDiv}>{"Baskets: "}{this.props.openBaskets.length}</p>
<hr style={horizontalLineStyle}/>
</DialogTitle>
<DialogContent>
<div style={centerDiv}>
<Table>
<TableHead>
<TableRow>
<TableCell style={tableTextStyle}>User</TableCell>
<TableCell style={tableTextStyle}>Total</TableCell>
<TableCell style=tableTextStyle}>Products</TableCell>
<TableCell style={tableTextStyle}>Date</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.props.baskets !== undefined ?
this.props.baskets.map(basket => {
return(
<TableRow key={basket.id}>
<TableCell style={tableTextStyle}>
{basket.user}
</TableCell>
<TableCell style={tableTextStyle}>
€{basket.total}
</TableCell>
<TableCell style={tableTextStyle}>
<Button onClick={this.onToggle}>
{basket.posBasketItems.length}
<Dialog
open={this.state.innerTableWindowOpen}
onClose={this.handleClose}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-
description"
>
<DialogTitle>
<p style={centerDiv}>
{"Cart: "}
{basket.length} Products
</p>
<hr style={horizontalLineStyle}/>
</DialogTitle>
<DialogContent>
<Table>
<TableHead>
<TableRow>
<TableCell>
Name
</TableCell>
<TableCell>
Price
</TableCell>
<TableCell>
Quantity
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{basket.items.map(item => {
return (
<TableRow key={item.id}>
<TableCell>
{item.name}
</TableCell>
<TableCell>
{item.price}
</TableCell>
<TableCell>
{item.quantity}
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</DialogContent>
</Dialog>
</Button>
</TableCell>
<TableCell>
{this.parseDate(basket.date)}
</TableCell>
<TableCell>
<Button
onClick={()=>this.setToCurrentBasket(basket)}
>
<ADD_TO_SHOPPING_CART />
</Button>
</TableCell>
</TableRow>
);
}) : ''}
</TableBody>
</Table>
</div>
</DialogContent>
<DialogActions>
<div>
<MuiThemeProvider theme={cancelButtonTheme}>
<Button
variant="raised"
onClick={this.closeOpenBasketsWindow}
color="secondary"
>
CANCEL
</Button>
</MuiThemeProvider>
</div>
</DialogActions>
</Dialog>
Here's onToggle() and the state
state = {
innerTableWindowOpen: false
};
onToggle = () => {
this.setState({
innerTableWindowOpen: !this.state.innerTableWindowOpen
});
}
I would appreciate any idea to fix this with <Dialog> or <Modal> or even something similar.
The idea is to have a short preview of what's in the basket before choosing one.
Thanks!

Related

When I render a button inside a material-ui table, the button is not clickable

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');

How can I expand the row only when that row was 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>

Can not render Table correctly in React

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>

display an full-width row in material-ui table react

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>

Iterate Array in Tabs in React

I have an array called paymentMethods and i want to iterate it to tabs? My problem is i can't iterate it.
Pls see my codesandbox here CLICK HERE
<div>
{paymentMethods && paymentMethods.length > 0 ? (
<Paper square className={classes.root}>
<Tabs
value={value}
onChange={handleChange}
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
aria-label="icon label tabs example"
>
<Tab icon={<PhoneIcon />} label="Card" />
<Tab icon={<FavoriteIcon />} label="Paypal" />
</Tabs>
<Grid container spacing={4}>
<Grid item xs={12} sm={6} md={3}>
<Card className={classes.card}>
<CardHeader className={classes.cardHeader} title={`****`} />
<CardContent className={classes.content}>
<Table className={classes.table} aria-label="simple table">
<TableBody>
<TableRow>
<TableCell variant="head">Type</TableCell>
<TableCell variant="body">Card</TableCell>
</TableRow>
<TableRow>
<TableCell variant="head">Card Number</TableCell>
<TableCell variant="body">***</TableCell>
</TableRow>
<TableRow>
<TableCell variant="head">Expiry Month</TableCell>
<TableCell variant="body">12/2</TableCell>
</TableRow>
<TableRow>
<TableCell variant="head">Expiry Year</TableCell>
<TableCell variant="body">2021</TableCell>
</TableRow>
<TableRow>
<TableCell variant="head">CVC</TableCell>
<TableCell variant="body">***</TableCell>
</TableRow>
</TableBody>
</Table>
</CardContent>
</Card>
</Grid>
</Grid>
</Paper>
) : (
<Typography>no available</Typography>
)}
</div>
Here I have tried to make a working example. You can organize your json for more efficient looping. I just made another constant to store more parameters to put inside the tabs.
{paymentmethodNames.map((p, index) => (
<Tab icon={p.icon} label={p.title} {...a11yProps(index)} />
))}
The tabs indeed need some index-based panel selection. The panels are filled with content by looping over paymentMethods JSON data. Just add a conditional statement when you will have a change in the JSON structure. For example, PayPal does not have CVC.
You are probably looking for something like this:
<Tabs
value={value}
onChange={handleChange}
variant="fullWidth"
indicatorColor="secondary"
textColor="secondary"
aria-label="icon label tabs example"
>
{paymentMethods.map(p => (
<Tab icon={<PhoneIcon />} label="{p.label}" />
))}
</Tabs>
Note that the label and onChange code is just a guess - you probably want to put some stuff from p into the template, but I don't know what exactly.

Categories