Trying to use react material-ui checkbox inside Dialog - reactjs

I'm trying to use material-ui checkbox inside dialog but onChange function seems not working. Please refer the following info for my code:
<Dialog open={showAssetListDialog}>
<DialogTitle id="responsive-dialog-title">
<h3 className="formHeader">Asset List</h3>
<hr />
</DialogTitle>
<DialogContent>
<Typography>
{ availableAssets && Object.keys(assetList).map((key, index) => (
<p>
<Checkbox
const asset_id = {assetList[index].value}
checked = {assetList[index].asset_id}
color = "primary"
onChange = {props.handleCheckboxChange('asset_id')}
onCheck = {props.handleCheckboxChange}
>
</Checkbox>
{assetList[index].label}
</p>
))}
</Typography>
</DialogContent>
<DialogActions>
<Button
color="success"
className="btnSave"
onClick={props.handleAssetListClose}
>
Done
</Button>
</DialogActions>
</Dialog>

Related

Need to get form values outside the form in a modal

I am using ANTD React UI library.
<Modal
width="1100px"
centered
footer={null}
title={
<div className="d-flex align-items-center">
<div className="flex-grow-1">Record Profiles</div>
<div className="mr-4">
<Button
htmlType="submit"
type="primary"
onClick={() =>{this.SaveData(this.form.getFieldValue())}}
icon={<SaveOutlined />}
className="save_btn"
loading={this.state.saving}>
</Button>
<Button
onClick={() => { this.props.onCancel() }}
htmlType="button"
type="primary"
className="cancel_btn ml-2"
icon={<CloseCircleOutlined />}>
</Button>
</div>
</div>
}
visible={true}
closable={false}
okText="Yes"
cancelText="No"
maskClosable={false}
>
<Form
autoComplete="off"
layout="horizontal"
ref={(r) => this.form = r}
initialValues={this.props.record}
onFinish={this.SaveData}
>
.
.
.
</Form>
</Modal>
I want to call the save and close buttons on top of the side of the title. It is displaying correctly, but due to outside form functionalities don't work because the form values don't get outside. Is there any method to get the values outside or form submit?

React-Bootstrap modal only show and delete last mapped element

i'm building eccommerce and in my cart i want to show a modal when user tap on delete icon but my modal always show and delete last element of my cart
how can i resolve this issue
here's my modal component:
const VerticalModal = ({ item, mShow, hide, name }) => {
return (
<Modal
show={mShow}
size="md"
centered
>
<Modal.Header>
<Modal.Title >
<h6>Remove from cart</h6>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p className="text-center">Are you sure you want to remove {name}</p>
</Modal.Body>
<Modal.Footer className="d-flex justify-content-between">
<Button variant="outline-secondary" size="sm" onClick={hide}>
Cancel
</Button>
<Button variant="outline-danger" size="sm" onClick={item}>
Remove
</Button>
</Modal.Footer>
</Modal>
);
};
here's my cart code :
{cart &&
cart.cartItems.length > 0 &&
cart.cartItems.map((item, index) => (
<Card
key={index}
className=" cart-card-magninn cart-card-shadow"
>
<Row className="p-3">
<Col>{item.img}</Col>
<Col>{item.name}</Col>
<Col md={2} xs={2}>
<button
onClick={() => setModalShow(true)}
>
<FontAwesomeIcon icon={faTrashAlt} />
</button>
<VerticalModal
mShow={modalShow}
hide={() => setModalShow(false)}
item={() => removeFromCartHandler(item.prodid)}
name={item.prodname}
/>
</Col>
</Row>
)}
You're creating four modals and whenever, the modal opens, it has the value of the last item. You should move modal out of the map function and store the selected item in a separate state and use that to delete the info.
Initialize the selected item as empty object.
const [selectedItem, setSelectedItem] = useState({})
Then, update the click method on the button.
<button
onClick={() => {
setModalShow(true)
setSelectedItem(item)
}}>
<FontAwesomeIcon icon={faTrashAlt} />
</button>
After that, move the modal code outside of the map function.
{modalShow ?
<VerticalModal
mShow={modalShow}
hide={() => {
setModalShow(false)
setSelectedItem({})
}}
item={() => {
removeFromCartHandler(selectedItem.prodid)
setSelectedItem({})
}
name={selectedItem.prodname}
/>
: null}
Updated code could be something like this
{cart &&
cart.cartItems.length > 0 &&
cart.cartItems.map((item, index) => (
<Card
key={index}
className=" cart-card-magninn cart-card-shadow"
>
<Row className="p-3">
<Col>{item.img}</Col>
<Col>{item.name}</Col>
<Col md={2} xs={2}>
<button
onClick={() => {
setModalShow(true)
setSelectedItem(item)
}}>
<FontAwesomeIcon icon={faTrashAlt} />
</button>
</Col>
</Row>
)}
{modalShow ?
<VerticalModal
mShow={modalShow}
hide={() => {
setModalShow(false)
setSelectedItem({})
}}
item={() => {
removeFromCartHandler(selectedItem.prodid)
setSelectedItem({})
}
name={item.prodname}
/>
: null}

Avoid re-render while open/close material-ui Dialog component

I've got some problem with omit re-render while click button which open Dialog component. Currently I use useState flag which toggle my Dialog component but I must avoid re-rendering because there's expensive operations on big data.
Anyone know approach how to Open Dialog by button Open and Close Dialog by click on Dialog's button Exit.
const Item = () => {
const popupRef = useRef()
const dialog = () => {
return(
<Dialog ref={popupRef}
keepMounted
fullWidth
maxWidth="md"
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description">
<DialogTitle id="alert-dialog-slide-title">
<WrapperDialogHeader>Filters</WrapperDialogHeader>
<WrapperDialogCloseBtn>
<IconButton aria-label="close" >
<CloseIcon />
</IconButton>
</WrapperDialogCloseBtn>
</DialogTitle>
<DialogContent>
Something
</DialogContent>
<DialogActions>
<Button variant="outlined"
// onClick={ What handler here? }
color="primary">
<WrapperDialogOptionBtn>Exit</WrapperDialogOptionBtn>
</Button>
</DialogActions>
</Dialog>
)
}
return(
<>
<IconButton onClick={ /* What method here */ }>
<Typography variant="body1" color="primary">
<FilterListIcon fontSize="small" color="primary"/><WrapperFontSpecialSmall>Filters</WrapperFontSpecialSmall>
</Typography>
</IconButton>
{ dialog() }
</>
Methods like popupRef.current.click() not exist in ES6 I suppose.
How to build mechanism which toggle dialog without re-render whole component Item.
Move the dialog to its own component and wrap in memo()
const Dialog = ({ open, onClose }) => {
return (
<Dialog
keepMounted // why? you said the content is huge, so why keep it mounted
fullWidth
maxWidth="md"
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
open={open}
onClose={onClose}
>
<DialogTitle id="alert-dialog-slide-title">
<WrapperDialogHeader>Filters</WrapperDialogHeader>
<WrapperDialogCloseBtn>
<IconButton aria-label="close" >
<CloseIcon />
</IconButton>
</WrapperDialogCloseBtn>
</DialogTitle>
<DialogContent>
Something
</DialogContent>
<DialogActions>
<Button variant="outlined" onClick={onClose} color="primary">
<WrapperDialogOptionBtn>Exit</WrapperDialogOptionBtn>
</Button>
</DialogActions>
</Dialog>
)
};
export default memo(Dialog); // IMPORTANT
In the Item component,
const Item = () => {
const [dialogOpen, setDialogOpen] = useState(false);
const handleDialogOpen = () => setDialogOpen(true);
// prevent function being recreated on state change
const handleDialogClose = useCallback(() => setDialogOpen(false), []);
return (
<>
<IconButton onClick={handleDialogOpen}>
<Typography variant="body1" color="primary">
<FilterListIcon fontSize="small" color="primary" /><WrapperFontSpecialSmall>Filters</WrapperFontSpecialSmall>
</Typography>
</IconButton>
<Dialog open={dialogOpen} onClose={handleDialogClose} />
</>
);
}
Sidenote, it appears the dialog contains some sort of filter UI, presumably one or more lists. You may want to have a look at react-window if you are going to create long lists.

My handler does not set the state - Material UI

I am using the component "Dialog" from Material UI.
When I click on the button to close the Dialog (which triggers handleCLose), it does not set the state to false.
I read a similar problem here: OnClick Listeners not working after closing full-screen dialog using react-material-ui
but I have not managed to save it so far.
const Transition = React.forwardRef(function Transition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
});
function Information() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
console.log(open)
};
return (
<div onClick={()=>handleClickOpen()}>
Information
<Dialog
open={open}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle id="alert-dialog-slide-title">{"Information"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-slide-description">
Blablabla
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary"> // The function is here
Close
</Button>
</DialogActions>
</Dialog>
</div>
);
}
export default Information
It looks like you have wrapped your dialog in a div with an onClick function that sets the dialog to open. What is happening is that onClick is being called whenever you click inside the dialog. So even when you click the close button it is calling handleClickOpen. Try separating them:
return (
<> // Add wrapping fragment
<div onClick={()=>handleClickOpen()}>
Information
</div> // close div here
<Dialog
open={open}
TransitionComponent={Transition}
keepMounted
onClose={handleClose}
aria-labelledby="alert-dialog-slide-title"
aria-describedby="alert-dialog-slide-description"
>
<DialogTitle id="alert-dialog-slide-title">{"Information"}</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-slide-description">
Blablabla
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="primary">
Close
</Button>
</DialogActions>
</Dialog>
</>
);
}

Refactoring react code

I have a class component that is a header-bar and when you click on an icon a dialog-box pop up where you can input data and save it. I am trying to split these two items- header-bar and dialog-box into two different components. Is the best way to do this to redirect the from the header-bar component to a new dialog-box component. At the moment i have both of them in one component.Thanks for the advice.
const{classes} = this.props
return (
<div>
<Dialog
open={this.state.open}
onClose={this.handleClose}
aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">Add Folder</DialogTitle>
<DialogContent>
<TextField
margin="normal"
onChange={this.handleChange('name')}
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary"
onChange={this.handleFieldChange}
value={this.state.value}>
Create
</Button>
</DialogActions>
</Dialog>
<AppBar position="static" className={classes.bar} >
<Toolbar>
<IconButton color="inherit" aria-label="createfolder">
<SvgIcon>
<path d={createfolder}
onClick={this.handleClickOpen}
name="firstName"/>
</SvgIcon>
</IconButton>
</Toolbar>
</AppBar>
</div>
);
No, the best way to do this is not to redirect but same way, in a more modular or component/react way. You can create a functional component of dialog box and include it in your main component,
In the below code the functional component has been made inside the main component class itself so it can access the this.
DialogBox = ({state}) =>(
<Dialog
open={state.open}
onClose={this.handleClose}
aria-labelledby="form-dialog-title">
<DialogTitle id="form-dialog-title">Add Folder</DialogTitle>
<DialogContent>
<TextField
margin="normal"
onChange={this.handleChange('name')}
/>
</DialogContent>
<DialogActions>
<Button onClick={this.handleClose} color="primary">
Cancel
</Button>
<Button onClick={this.handleClose} color="primary"
onChange={this.handleFieldChange}
value={state.value}>
Create
</Button>
</DialogActions>
</Dialog>
)
Now include this in your header-bar component,
const{classes} = this.props
return (
<div>
<AppBar position="static" className={classes.bar} >
<Toolbar>
<IconButton color="inherit" aria-label="createfolder">
<SvgIcon>
<path d={createfolder}
onClick={this.handleClickOpen}
name="firstName"/>
</SvgIcon>
</IconButton>
</Toolbar>
</AppBar>
<this.DialogBox state={this.state}/>
</div>
);

Resources