how to close 2 model in react? - javascript

i am working on reactJs. I tried to generate user's gallery when user click on its avatar.I am using react-grid-gallery package for this.I uses semantic ui react for desiging.My code is:
<Modal trigger={<Image
src={data.profile_photo}
alt={data.name}
size="massive"
avatar
/>}
style={ { height: "90%" } }>
<Modal.Content >
<Modal.Description>
<Gallery images={Images} enableImageSelection='false' isOpen={true} showLightboxThumbnails='true' rowHeight='120'/>
</Modal.Description>
</Modal.Content>
</Modal>
Here Images is array of images which i already generated.Its works well and it generate slider.My question is this when i close slider still modal open.Basically there are two modal one for gallery and another is semantic.I want when i close Gallery Modal it should close semantic modal as well.how can i do it?? i tried to do by setting modelopen state but it not worked.

You can use lightboxWillClose to toggle modal's open.
It would be something like this:
state = { modalOpen: false }
handleModalClose = () => this.setState({ modalOpen = false })
handleModalOpen = () => this.setState({ modalOpen = true })
<Modal
open = {this.state.modalOpen}
trigger={<Image
onClick = {this.handleModalOpen}
src={data.profile_photo}
alt={data.name}
size="massive"
avatar
/>}
style={ { height: "90%" } }>
<Modal.Content >
<Modal.Description>
<Gallery
images={Images}
enableImageSelection='false'
isOpen={true}
showLightboxThumbnails='true'
rowHeight='120'
lightboxWillClose={this.handleModalClose}
/>
</Modal.Description>
</Modal.Content>
</Modal>
I haven't tested it so you might have to tweak it a little bit. But you get the idea.

Related

Changing Popover internal state - Headless UI

How do i change the internal state of the Popover with a function outside the component: Like the openPopover function i created below.
const openPopover = () => {
setPopoverOpen(true) // Example..
}
<Popover>
{({open}: {open: boolean}) => {
// How do i change the open state here from outside the Popover.
return (
<>
<Popover.Button>
Test
</Popover.Button>
{open && (
<Popover.Panel static>
Test
</Popover.Panel>
)}
</>
)
}}
</Popover>
Popover manages open state internally and doesn't expose a way to change this.
To keep track of the open state however, you could use a useEffect inside the render prop.
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
<Popover>
{({open}: {open: boolean}) => {
useEffect(() => {
setIsPopoverOpen(open)
}, [open]);
return (
<>
<Popover.Button>
Test
</Popover.Button>,
{open && (
<Popover.Panel static>
Test
</Popover.Panel>
)}
</>
)
}}
</Popover>
The toggling behavior is being handled by <Popover.Button> component. Alternatively, Popover and Popover.Panel exposes a close() method to close the popover. You could always use Portals to make the component available in parent for handling either toggling or executing the close() method.
import { createPortal } from 'react-dom';
<Popover>
{({ open, close }) => {
return (
<>
{createPortal(
<Popover.Button>
Toggle popover
</Popover.Button>,
// html node where we will position this button
)}
{open && (
<Popover.Panel static>
Test
</Popover.Panel>
)}
{createPortal(
<button onClick={close()}>
Close Popover
</button>,
// html node where we will position this close button
)}
</>
)
}}
</Popover>

Dialog of material UI has afterimage when being closed

Introduction
Bascially <Dialog /> receives open and onClose as props. open is boolean from state and onClose is a function that changes the state.
I made <CustomModal /> that wraps <Dialog />, which receives another prop content that defines what to display on <Dialog />.
// CustomModal.jsx
const CustomModal = props => (
<Dialog {...props} sx={{ '& .MuiDialog-paper': { padding: '2em' } }}>
{props.content}
</Dialog>
);
And I'm delivering handlers using context so that my modal could be open and closed everywhere.
// modalHandlersContext.js
const initialState = {
open: false,
content: null,
};
const ModalHandlersProvider = ({ children }) => {
const [modal, setModal] = useState(initialState);
const handlers = {
openModal: payload => setModal({ open: true, ...payload }),
closeModal: () => setModal(initialState),
};
return (
<ModalHandlersContext.Provider value={handlers}>
{children}
<CustomModal
open={modal.open}
onClose={handlers.closeModal}
content={modal.content}
></CustomModal>
</ModalHandlersContext.Provider>
);
};
When I want to open modal somewhere, I execute a function like this
const onLogin = () =>
openModal({
content: <h1>component</h1>,
});
That is, I pass a component. (I used h1 for a simple example)
Main subject
But when I close it, it's not clean.
I experimented on this to check when this happens.
It happens
With css, display something from props(same code as above)
const CustomModal = props => (
<Dialog {...props} sx={{ '& .MuiDialog-paper': { padding: '2em' } }}>
{props.content}
</Dialog>
);
It doesn't happen
Without css, display something from props
const CustomModal = props => (
<Dialog {...props}>
{props.content}
</Dialog>
);
2,3. With/Without css, display just plain text
const CustomModal = props => (
<Dialog {...props} sx={{ '& .MuiDialog-paper': { padding: '2em' } }}>
content
</Dialog>
);
const CustomModal = props => (
<Dialog {...props}>
content
</Dialog>
);
So after that, I tried using <DialogContent /> instead of css but It didn't work. But I have tried using <Modal /> instead of <Dialog /> and it hasn't caused any problems.
I wanna use <Dialog /> if possible but now can't find the cause.
Can anyone help?

In React how can I trigger a custom button's click event from a different compoennt's event handler?

I have a React app which uses Material UI for it's interface. I've created a custom button component which styles the default Material UI button and also uses redux.
The render() function of my button component looks like this:
return (
<div className={classes.buttonWrapper}>
<Button
ref={this.props.innerRef}
disabled={loading || disabled}
onClick={this.handleClick}
{...other}>
<React.Fragment>
{children}
{this.buildLoader(loading, classes)}
</React.Fragment>
</Button>
</div>
);
What I want is to be able to include this button on a page and have the UI trigger its click event by other means other than clicking on it. For example, on a login form I want a user who currently has focus on the password textbox to be able to trigger the button click by hitting the Return/Enter key.
I'm sure I need to use the concept of forwarding refs in React, but I'm fairly new to React and can't get it working. You can see on my button I've defined a ref set to this.props.innerRef. My button component (called WaitingButton) is exported like this:
const withInnerRef = React.forwardRef((props, ref) => <WaitingButton
innerRef={ref} {...props}
/>);
var component = withStyles(styles)(withInnerRef);
export default connect(mapStateToProps, mapDispatchToProps)(component);
I've then added this button to a form like this:
<Paper>
<TextField
style={{marginBottom: '8px'}}
label="A textbox!"
fullWidth
onKeyPress={(e) => { if (e.key === "Enter") this.triggerClick(); }} />
<WaitingButton
ref={this.submitButton}
variant="contained"
color="primary"
onClick={(e) => {
console.log('Button clicked :)', e.target);
}}>
Press enter in textbox!
</WaitingButton>
</Paper>
See I've assigned the button's ref and in this page's constructor I've initialised the ref in the constructor using this.submitButton = React.createRef();
Finally the triggerClick looks like this:
triggerClick() {
console.log('CLICK', this.submitButton.current);
this.submitButton.current.click();
}
When I hit enter in the textbox, I can inspect the value assigned to this.submitButton.current and can see it is the Redux connect object that I've wrapped my button with. However, I also get the error this.submitButton.current.click is not a function so clearly the ref isn't getting forwarded all the way to the button itself.
I'm afraid I'm a bit lost so appealing for your help!
Just want to ensure, what you want is: when user press Enter while typing on the textfield, the button will show a loading visual, right?
I think you don't have to pass ref to the button component, you could just pass state isLoadingShown into your WaitingButton
WaitingButton.js
return (
<div className={classes.buttonWrapper}>
<Button
ref={this.props.innerRef}
disabled={loading || disabled}
onClick={this.handleClick}
{...other}>
<React.Fragment>
{children}
{this.props.isLoadingShown && this.buildLoader(loading, classes)}
</React.Fragment>
</Button>
</div>
);
Then in the form component
state = {
isLoadingShown: false,
}
triggerClick() {
this.setState({ isLoadingShown: true })
}
render(){
...
<Paper>
<TextField
style={{marginBottom: '8px'}}
label="A textbox!"
fullWidth
onKeyPress={(e) => { if (e.key === "Enter") this.triggerClick(); }} />
<WaitingButton
variant="contained"
color="primary"
isLoadingShown={this.state.isLoadingShown}
onClick={(e) => {
console.log('Button clicked :)', e.target);
}}>
Press enter in textbox!
</WaitingButton>
</Paper>
...
}
don't forget to set isLoadingShown to false again in componentWillUnmount
I just tried to reproduce your case. And I created a codesandbox for it. I think I found the problem. It seems React.forwardRef only works with prop name forwardedRef so try to rename the innerRef property to forwardedRef in your code.
const withInnerRef = React.forwardRef((props, ref) => <WaitingButton
forwardedRef={ref} {...props}
/>);
and also in your render() function
<Button
ref={this.props.forwardedRef}
disabled={loading || disabled}
onClick={this.handleClick}
...
You can try it with my simplified codesandbox https://codesandbox.io/s/intelligent-cori-rb5ce

How to fix redirection problems in a react-material menu

With my menu I encounter different problem.
For starters, in the first RETURN, I have a TREEITEM with a LISTITEM and a LISTITETEXT.
I put an OnClick in the LISTITETEXT so that if the id of my menu is equal to a value I authorize a redirection.
However, the redirection reloads the page and this is not the purpose of my menu when I use react.
Second, I have my other RETURN which contains my submenu.
it is displayed correctly, when I click on the TREEITEM, I am redirected to the right page.
However, I have the error in the console:
Warning: You tried to redirect to the same route you're currently on:
"/extranetV1/prospect"
{stoMenu && (
<TreeView
style={layout.menu}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
>
{stoMenu.root.children.map(menu => {
return (
<TreeItem
key={menu.nodeId}
nodeId={menu.nodeId}
label={
<ListItem style={layout.menuListItem} className={menu.iconCls}>
<ListItemText style={layout.menuText} primary={menu.text} onClick={() => {
if (menu.id === '/accueil') {
window.location.assign(menu.id);
}
}} />
</ListItem>
}
>
{menu.children.map(child => {
return (
<TreeItem
key={child.nodeId}
nodeId={child.nodeId}
label={child.text}
>
<Redirect to={child.id}/>
</TreeItem>
);
})}
</TreeItem>
);
})}
</TreeView>
)}
For both scenarios you use redirection in react wrong.
You need to use react router for redirection inside react app and instead of window.location.assign(menu.id) it will be props.history.push(menu.id).
I see in the second one you use Redirect component. The problem is that you trigger redirect each time in the loop. You should set some state instead and trigger render with condition earlier in the code.
const MyComponent = (props) => {
const [state, setState] = useState({ pathToRedirect: null });
const handleRedirect = (to) => {
setState({ pathToRedirect: to});
}
render () {
if (state.pathToRedirect) {
return <Redirect to={state.pathToRedirect} />;
}
//render list with handleRedirect onClick
return (...);
}
To correct my problem of reloading the page, I integrated this:
<TreeItem
key={menu.nodeId}
nodeId={menu.nodeId}
label={
<ListItem style={layout.menuListItem} className={menu.iconCls}>
<ListItemText style={layout.menuText} primary={menu.text} onClick={() => {
if (menu.id === '/accueil') {
this.props.history.push(menu.id);
}
}} />
</ListItem>
}
>
I removed the REDIRECT by this in my sub menu :
<TreeItem
key={child.nodeId}
nodeId={child.nodeId}
label={child.text}
onClick={() => {
if (child.id) {
this.props.history.push(child.id);
}
}}
/>

Displaying bootstrap modal in reactJs

I am trying to display a bootstrap modal in my reactJs project. I have buttons with different IDs with different content displayed in a map function. I want the each modal content to correspond to the ID of the button clicked. I am following this examaple - https://react-bootstrap.github.io/components/modal/ but there is no way to specify the id here.
How do I resolve this?
At button, you can pass content to onClick and set it to state
handleShow = (data) => {
this.setState({ show: true, title: data.title });
}
render() {
return (
<div>
{
listData.map((data, index) => {
return (
<Button key={index} bsStyle="primary" bsSize="large" onClick={() => this.handleShow(data)}>
Launch demo modal
</Button>
);
})
}
</div>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Body>
{this.state.title}
</Modal.Body>
</Modal>

Categories

Resources