I'm opening a dialog component when i click the DELETE function button on my users list. When i click it, should show the dialog component. My problem is why i can't open it. I'm using redux to pass data to it.
Pls see this codesandbox link
CLICK HERE
import { dialogConstants } from "../constants";
export const initialState = {
title: null,
details: null,
isOpen: null
};
const dialogReducer = (state = initialState, action) => {
console.log(action.payload);
switch (action.type) {
case dialogConstants.SET_DIALOG_DETAILS:
return {
...state,
isOpen: action.payload.isOpen,
title: action.payload.title,
details: action.payload.details
};
default:
return state;
}
};
export default dialogReducer;
You are not importing Dialogs in user.js. So when you click button your dialog will not open. Try this:
In user.js:
...
import DeleteDialog from "./dialog";
import { useDispatch } from "react-redux";
import { deleteUser } from "./actions";
export default function User() {
const dispatch = useDispatch();
const [selectedUser, setSelectedUser] = React.useState({});
const [open, setDialogOpen] = React.useState(false);
const handleOnDelete = user => {
setSelectedUser(user);
setDialogOpen(true);
};
const handleOnAgree = () => {
// do action to handle on agree deleting an user
dispatch(deleteUser({ title: "Delete User", details: selectedUser }));
setDialogOpen(false);
};
return (
<div>
<Paper>
<TableContainer>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
<TableCell>First Name</TableCell>
<TableCell>Last Name</TableCell>
<TableCell>Email Address</TableCell>
<TableCell>Actions</TableCell>
<TableCell />
</TableRow>
</TableHead>
<TableBody>
<TableRow>
<TableCell>JJJ</TableCell>
<TableCell>BBB</TableCell>
<TableCell>enfoie</TableCell>
<TableCell>
<Button variant="contained">Edit</Button>
<Button
variant="contained"
onClick={() => handleOnDelete({ id: 1, name: "JJJ" })}
>
Delete
</Button>
</TableCell>
</TableRow>
</TableBody>
</Table>
</TableContainer>
</Paper>
<DeleteDialog
user={selectedUser}
open={open}
onAgree={handleOnAgree}
onDisagree={() => setDialogOpen(false)}
/>
</div>
);
}
In dialog.js:
import React from "react";
import Button from "#material-ui/core/Button";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogTitle from "#material-ui/core/DialogTitle";
import Slide from "#material-ui/core/Slide";
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
const DeleteDialog = ({ user, open, onAgree, onDisagree }) => {
return (
<div>
<Dialog
open={open}
TransitionComponent={Transition}
keepMounted
onClose={onDisagree}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle id="alert-dialog-slide-title">
<span style={{ fontWeight: "bold" }}>
{" "}
User: {user.name} - {user.id}
</span>
</DialogTitle>
<DialogActions>
<Button variant="contained" size="small" onClick={onDisagree}>
Cancel
</Button>
<Button variant="contained" size="small" onClick={onAgree}>
Confirm
</Button>
</DialogActions>
</Dialog>
</div>
);
};
export default DeleteDialog;
Related
wanted to add a new element in a table with Materials UI,using a component that adds a new row.The component takes data from user and the idea is to send this data to the Table component.How can I transfer this data from DialogBoxAddPost to Table component and how to mix the data from the API and the new user added data.
Thank you!
Table component:
import * as React from 'react';
import { styled } from '#mui/material/styles';
import Table from '#mui/material/Table';
import TableBody from '#mui/material/TableBody';
import TableCell, { tableCellClasses } from '#mui/material/TableCell';
import TableContainer from '#mui/material/TableContainer';
import TableHead from '#mui/material/TableHead';
import TableRow from '#mui/material/TableRow';
import Paper from '#mui/material/Paper';
import { Button } from '#mui/material';
import './App.css';
import { useEffect, useState } from "react";
import DialogBoxEdit from './DialogBoxEdit';
export default function Tableall() {
const [posts, setPosts] = useState([])
const fetchData = () => {
fetch("https://jsonplaceholder.typicode.com/posts").then(response => {
return response.json()
})
.then((data) => {
setPosts(data.slice(0, 6));
});
};
useEffect(() => {
fetchData()
}, []);
const handleDelete = (postIndex) => {
setPosts((prevPosts) =>
prevPosts.filter((_, index) => index !== postIndex)
);
};
return (
<TableContainer sx={{
marginLeft:'auto',
width:'max-content',
marginRight:'auto',
}}component={Paper}>
<Table sx={{ minWidth: 700,tableLayout:'auto' }} aria-label="customized table">
<TableHead>
<TableRow>
<StyledTableCell sx={{width:250}}>Title</StyledTableCell>
<StyledTableCell align="center" sx={{width:500}}>Description</StyledTableCell>
<StyledTableCell align="center" sx={{width:100}}></StyledTableCell>
<StyledTableCell align="center"sx={{width:100}}></StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{posts.map((post,postIndex) => (
<StyledTableRow key={post.id}>
<StyledTableCell component="th" scope="row">{post.title}</StyledTableCell>
<StyledTableCell align="center">{post.body}</StyledTableCell>
<StyledTableCell align="center"><DialogBoxEdit dataParent1={post.title} dataParent2={post.body} /></StyledTableCell>
<StyledTableCell align="center"><Button variant="outlined" color="error" onClick={() => handleDelete(postIndex)}>Delete</Button></StyledTableCell>
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
Dialogbox to add a new elements in a table.
import * as React from 'react';
import Button from '#mui/material/Button';
import Dialog from '#mui/material/Dialog';
import DialogActions from '#mui/material/DialogActions';
import DialogContent from '#mui/material/DialogContent';
import DialogContentText from '#mui/material/DialogContentText';
import DialogTitle from '#mui/material/DialogTitle';
import useMediaQuery from '#mui/material/useMediaQuery';
import { useTheme } from '#mui/material/styles';
import Table from './TableAll';
import TextField from '#mui/material/TextField';
import Divider from '#mui/material/Divider';
import {useState} from 'react';
export default function ResponsiveDialog() {
const [open, setOpen] = React.useState(false);
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('md'));
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
const [message, setMessage] = useState('');
const [message2, setMessage2] = useState('');
const handleChange = event => {
setMessage(event.target.value);
};
const handleChange2 = event => {
setMessage2(event.target.value);
};
const handleClick = event => {
event.preventDefault();
console.log(message,message2);
setOpen(false);
};
return (
<div>
<Button variant="contained" sx={{right:477,top:-10,height:48}} color='warning' size='large' onClick={handleClickOpen}>
Add new +
</Button>
<Dialog
fullScreen={fullScreen}
open={open}
onClose={handleClose}
aria-labelledby="responsive-dialog-title"
fullWidth
maxWidth="sm"
>
<DialogTitle id="responsive-dialog-title">{"Add new post"}
</DialogTitle>
<DialogContent>
<Divider variant="middle" />
<DialogContentText>
Title
</DialogContentText>
<TextField id="outlined-basic" onChange={handleChange} value={message} name="message" label="Title" variant="outlined" style = {{width: 500}} />
<DialogContentText>
Description
</DialogContentText>
<TextField id="outlined-basic" onChange={handleChange2} value={message2} multiline rows={4} label="Description" variant="outlined" style = {{width: 500}} />
</DialogContent>
<DialogActions>
<Button autoFocus variant="outlined" color='error' onClick={handleClose}>
Exit
</Button>
<Button color='success' variant="outlined" onClick={handleClick} autoFocus>
Add
</Button>
</DialogActions>
</Dialog>
</div>
);
}
Actually I am facing three issues that is
I have used useState and trying to toggle between icons & button but vise versa is not happening
If I call the edit Icon it All table the Edit Icon are changing to other save button
Once I am on edit I need to target the paticular row only
All above three table will be handled by one change but How i am not sure
Here is the code
import React, { useState } from 'react';
import { ReactComponent as EditIcon } from '../../../assets/icons/edit-icon.svg';
import './ProductLineTable.css';
import { ReactComponent as AddIcon } from '../../../assets/icons/add-icon.svg';
import {
Typography,
Table,
TableHead,
TableRow,
TableCell,
TableContainer,
TableBody,
Button,
Input,
InputAdornment,
TextField
} from '#material-ui/core';
export const data= [
{ id:1,Name:'test1',Class: 6Gender:'M'},
{ id:2,Name:'test1',Class: 6Gender:'M'},
{ id:3,Name:'test1',Class: 6Gender:'M'},
];
const Table = props => {
const [isEdit, setIsEdit] = useState(false);
const editClick=()=>{
setIsEdit(true);
}
const cancelClick=()=>{
setIsEdit(false);
}
return (
<>
<TableContainer className='product-line-table'>
<Table>
{data.map((k, index) => (
<TableRow key={k.Id}>
<TableCell>
<Typography>
{isEdit ? (
<TextField
data-test='firstname-input'
// label='Enter Product Code'
className='form-input user-search-textbox'
value={k.Name}
// onChange={e => {
// handleChange(e, index, 'Product');
// }}
/>
) : (
k.Name
)}
</Typography>
</TableCell>
<TableCell>
<Typography>{k.Class}</Typography>
</TableCell>
<TableCell>
<Typography>{k.Gender}</Typography>
</TableCell>
<TableCell align='center'>
<Typography>
{isEdit ? (
<>
<Button
variant='contained'
color='primary'
size='small'
onClick={() => {
cancelClick
}}
>
Save
</Button>
<Button
color='secondary'
variant='outlined'
type='reset'
size='small'
className='user-reset-btn'
onClick={() => {
cancelClick
}}
>
Cancel
</Button>
</>
) : (
<Button
onClick={editClick}
>
<EditIcon />
</Button>
)}
</Typography>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
);
};
export default Table;
Hello here is my problem, I have implemented a table that table fill when I choose some suggestion. The table contains three columns of (product, qty, balance and add button) So when I click add button it displays some popup form.
So I want to do when adding some quantity in the popup menu and after that click the add button it will reduce from the balance field in the table according to the selected product. Below is the table array.
import React, { useState } from "react"
import {
Grid,
Table,
TableContainer,
TableHead,
TableRow,
TableCell,
Paper,
TableBody,
Button
} from "#material-ui/core"
import AddItem from "./AddItem"
import { useStyles } from "../../../../styles/classes"
export default function ItemsList({
cart,
handleChange,
handleBlur,
values,
setFieldValue,
volumes
}) {
const [open, setOpen] = useState(false)
const [productId, setProductId] = useState("")
const [factoryId, setFactoryId] = useState("")
const handleClickOpen = (productId, factoryId) => {
setProductId(productId)
setFactoryId(factoryId)
setOpen(true)
}
const handleClose = (value) => {
setOpen(false)
}
const addToList = (factory) => {
setOpen(false)
const product = cart.find(
(item) => item.productId === Number(productId)
)
const item = {
productId: productId,
productName: product.productName,
containerNo: values.containerNo,
sealNo: values.sealNo,
qty: values.qty,
factoryId: factory.id,
factory: factory.name,
printDate: values.printDate,
printTime: values.printTime,
palletNo: values.palletNo,
}
const idx = values.volumes.findIndex(e=>e.number === Number(values.noOfContainers))
console.log(idx)
const current = values.volumes[idx].data;
current.push(item)
setFieldValue(`volumes[${idx}].data`,current)
//sum of qty in loaded volumes for this product
values.invoiceItems.forEach((item, idx) => {
item.balance = (Number(item.balance) - Number(values.qty))
})
setFieldValue('invoiceItems', values.invoiceItems)
}
const classes = useStyles()
return (
<Grid item md={12} sm={12} xs={12}>
<TableContainer component={Paper} >
<Table className={classes.table} size="small">
<TableHead>
<TableRow>
<TableCell align="left">Product</TableCell>
<TableCell align="left">Quantity</TableCell>
<TableCell align="left">Balance</TableCell>
<TableCell align="left">Add</TableCell>
</TableRow>
</TableHead>
<TableBody>
{cart.map((row, i) => (
<TableRow key={i}>
<TableCell align="left">{row.productName}</TableCell>
<TableCell align="left">{row.qty}</TableCell>
<TableCell align="left">{row.balance}</TableCell>
<TableCell align="left">
<Button
variant="outlined"
size="small"
color="secondary"
onClick={() => {
handleClickOpen(row.productId)
}}>
add
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
<AddItem
open={open}
onClose={handleClose}
handleChange={handleChange}
handleBlur={handleBlur}
values={values}
addToList={addToList}
volumes={volumes}
/>
</Grid>
)
}
import React, { useState} from "react"
import {
Grid,
Card,
CardContent,
CardActions,
Button,
CardHeader,
} from "#material-ui/core"
import Alert from "#material-ui/lab/Alert"
import axios from 'axios'
//validation
import { Formik, Form } from "formik"
import * as Yup from 'yup'
import { useStyles } from "../../../styles/classes"
import ItemList from "./subComponents/ItemsList"
import MetaData from "./subComponents/MetaData"
import ContainerList from "./subComponents/ContainerList"
import {useInitialValues} from '../../../hooks/useLoadingInfoData'
// validation schema
let validationSchema = Yup.object().shape({
volumes: Yup.string().required(),
})
export default function LoadingInfo(props) {
const classes = useStyles()
const [initialValues, setInitialValues] = useInitialValues()
const [volumes, setVolumes] = useState([])
const [alert, setAlert] = useState({
showAlert: false,
severity: "success",
message: "",
})
// create method
const submit = async (e, { resetForm }) => {
try {
await axios.post("/loadingInfo", e)
resetForm()
setAlert({
showAlert: true,
severity: "success",
message: "Loading Information created successfully!",
})
} catch (error){
if (error.response.status === 422) {
setAlert({
showAlert: true,
severity: 'error',
message: 'Loading information already exists!',
})
} else {
setAlert({
showAlert: true,
severity: 'error',
message: 'Loading information creation failed!',
})
}
}
}
return (
<Grid container className={classes.root} spacing={1}>
<Grid item xs={12} sm={12} md={12}>
<Formik
initialValues={initialValues}
onSubmit={submit}
validationSchema={validationSchema}
enableReinitialize>
{({
isValid,
dirty,
values,
handleChange,
handleBlur,
setFieldValue,
errors,
}) => {
return (
<Form>
<Card variant="outlined" style={{marginBottom: '1rem'}}>
<CardHeader title="Loading Information"></CardHeader>
<CardContent>
<Grid container spacing={1}>
<MetaData
values={values}
handleChange={handleChange}
handleBlur={handleBlur}
setAlert={setAlert}
setFieldValue={setFieldValue}
/>
<ItemList
cart={values.invoiceItems}
values={values}
handleChange={handleChange}
handleBlur={handleBlur}
setFieldValue={setFieldValue}
volumes={volumes}
/>
</Grid>
</CardContent>
</Card>
<Card variant="outlined">
<CardContent>
{values.volumes.map( (data , idx) =>
<ContainerList values={data} idx={idx} setFieldValue={setFieldValue}/>
)}
</CardContent>
<CardActions>
<Button
variant="contained"
color="primary"
type="submit"
disabled={!dirty || !isValid}>
create
</Button>
</CardActions>
</Card>
</Form>
)
}}
</Formik>
</Grid>
<Grid></Grid>
{alert.showAlert && (
<Grid item md={12}>
<Alert
severity={alert.severity}
onClose={() =>
setAlert({
...alert,
showAlert: false,
})
}>
{alert.message}
</Alert>
</Grid>
)}
</Grid>
)
}
I am trying to create dynamic input fields in my react application(using Material UI) on the click of a button. Whenever the add button is clicked, it creates a new input field inside a dialog box but I can't seem to enter any values in the text-field. Following is my app.js file -
import React from "react";
import "./styles.css";
import Button from "#material-ui/core/Button";
import TextField from "#material-ui/core/TextField";
import Dialog from "#material-ui/core/Dialog";
import DialogActions from "#material-ui/core/DialogActions";
import DialogContent from "#material-ui/core/DialogContent";
import DialogContentText from "#material-ui/core/DialogContentText";
import DialogTitle from "#material-ui/core/DialogTitle";
import IconButton from "#material-ui/core/IconButton";
import DeleteIcon from "#material-ui/icons/Delete";
import { Box, Grid } from "#material-ui/core";
export default function App() {
const [open, setOpen] = React.useState(false);
const [values, setValues] = React.useState([]);
const [text, setText] = React.useState("");
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
setValues([]);
};
const handleChangeText = (e) => {
setText(e.target.value);
};
const addValue = () => {
setValues([...values, ""]);
};
const handleValueChange = (index, e) => {
values[index] = e.target.value;
console.log(values);
setValues(values);
};
const deleteValue = (jump) => {
setValues(values.filter((j) => j !== jump));
};
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Create
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="form-dialog-title"
>
<DialogTitle id="form-dialog-title">New Dialog</DialogTitle>
<DialogContent>
<DialogContentText>Sample Text.</DialogContentText>
<TextField
autoFocus
margin="dense"
value={text}
onChange={handleChangeText}
label="Text"
fullWidth
/>
{values.map((jump, index) => (
<Box key={"jump" + index}>
<Grid container spacing={1} alignItems="flex-end">
<Grid item xs={10}>
<TextField
autoFocus
margin="dense"
label="Value"
value={jump || ""}
onChange={(e) => handleValueChange(index, e)}
fullWidth
/>
</Grid>
<Grid item xs={2}>
<div
className="font-icon-wrapper"
onClick={() => deleteValue(jump)}
>
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</div>
</Grid>
</Grid>
</Box>
))}
</DialogContent>
<Button onClick={addValue} color="primary">
Add
</Button>
<DialogActions>
<Button onClick={handleClose} variant="contained" color="secondary">
Cancel
</Button>
<Button onClick={handleClose} variant="contained" color="primary">
Create
</Button>
</DialogActions>
</Dialog>
</div>
);
}
Here is the code sandbox link.
I have a simple text field inside the dialog box also that works perfectly. The problem is with the dynamic fields. I don't know what mistake I am making in this code. Someone please help me out. Thanks in advance
You a have problem in the function handleValueChanges, don't use mutation use immutable data.
the correct code:
const handleValueChange = (index, e) => {
const updatedValues = values.map((value, i) => {
if(i === index) {
return e.target.value
}else {
return value
}
})
setValues(updatedValues);
};
You can test from here: https://codesandbox.io/s/dynamic-textfield-forked-gck25?file=/src/App.js
I am trying to trigger the Redirect React Dom
that is my button component in the handleMenuItemClick() function. But nothing happens.
I have tried a bunch of stuff but but still no success.
How can I make the both work together? My best try was to make a function that return the Redirect component as I saw in one post around, but still no success.
My Code:
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { Grid, Button, ButtonGroup, ArrowDropDownIcon, ClickAwayListener, Grow, Paper, Popper, MenuItem, MenuList, Link } from '#material-ui/core/Grid';
const SplitButton = (props) => {
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef(null);
const [selectedIndex, setSelectedIndex] = React.useState(1);
const myGroups = props.myGroups
const handleMenuItemClick = (event, index) => {
setSelectedIndex(index);
setOpen(false);
return <Redirect to={`/groups/${index}`} />
};
const handleToggle = () => {
setOpen((prevOpen) => !prevOpen);
};
const handleClose = (event) => {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}
setOpen(false);
};
return (
<>
<ButtonGroup variant="contained" color="primary" ref={anchorRef} aria-label="split button">
<Button onClick={null}>My Groups</Button>
<Button
color="primary"
size="small"
aria-controls={open ? 'split-button-menu' : undefined}
aria-expanded={open ? 'true' : undefined}
aria-label="select merge strategy"
aria-haspopup="menu"
onClick={handleToggle}
>
<ArrowDropDownIcon />
</Button>
</ButtonGroup>
<Popper open={open} anchorEl={anchorRef.current} role={undefined} transition disablePortal>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom',
}}
>
<Paper>
<ClickAwayListener onClickAway={handleClose}>
<MenuList id="split-button-menu">
{ myGroups.map((group) => (
<MenuItem
key={group.id}
onClick={(event) => handleMenuItemClick(event, group.id)}
>
{group.title}
</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</>
);
}
export default SplitButton
You can redirect user via 2 methods: useHistory or <Redirect />
useHistory hook
If you want to redirect the user directly on click, you can treat the code imperatively and tell React what to do:
const history = useHistory();
const handleMenuItemClick = (event, index) => {
setSelectedIndex(index);
setOpen(false);
history.push(`/groups/${index}`)
};
More info https://reactrouter.com/web/api/Hooks/usehistory
Redirect component
Or if you feel more comfortable using React's default declarative model, you can say what's changed and allow your code to react to this change:
const [redirectUrl, setRedirectUrl] = useState('')
const handleMenuItemClick = (event, index) => {
setSelectedIndex(index);
setOpen(false);
setRedirectUrl(`/groups/${index}`)
};
if (redirectUrl) {
return <Redirect to={redirectUrl} />
}
return (
<>
<ButtonGroup variant="contained" color="primary" ref={anchorRef} aria-label="split button">
<Button onClick={null}>My Groups</Button>
<Button
...
More info https://reactrouter.com/web/api/Redirect