How to use multiple modal in the same page? - reactjs

class dashboard extends Component {
constructor(props) {
super(props);
this.state = {
show: false,
msg: false
}
}
handelModal1() {
this.setState({ show: !this.state.show })
}
handelModal2() {
this.setState({ msg: !this.state.msg })
}
render() {
return (
<div>
<>
<Button variant="primary" onClick={() => { this.handelModal1() }}
one
</Button>
<Modal show={this.state.show} >
<Modal.Header>
<Modal.Title>Modal one</Modal.Title>
</Modal.Header>
<Modal.Body> hello </Modal.Body>
<Modal.Footer>
<Button onClick={() => { this.handelModal1() }}>
OK
</Button>
</Modal.Footer>
</Modal>
</>
</div>
<div>
<>
<Button variant="primary" onClick={() => { this.handelModal2() }}
two
</Button>
<Modal msg={this.state.msg} >
<Modal.Header>
<Modal.Title>Modal two</Modal.Title>
</Modal.Header>
<Modal.Body> hello </Modal.Body>
<Modal.Footer>
<Button onClick={() => { this.handelModal2() }}>
OK
</Button>
</Modal.Footer>
</Modal>
</>
</div>
)
}
I am trying to use two modals on the same page.
The first modal is working and I'm getting the pop-up, but the second modal is now working.
There is no pop up when I click on the second modal. Is there any simple way to use two modals on the same page???

You have to set <Modal show={this.state.msg} > Instead<Modal msg={this.state.msg} >
or
Maybe this link will help you React Rendering Multiple Modals in Same Component

Related

Calling modal from if condition React

I have two modals in React:
<Modal isOpen={this.state.activeModal === 'addedToCart'} id="#addedToCart" show={this.state.show} onHide={()=>{this.handleModal()}}>
<Modal.Header closeButton> my heading</Modal.Header>
<Modal.Body> Added Successfully to cart!</Modal.Body>
<Modal.Footer>
<Button onClick={()=>{this.handleModal()}}>Continue Shopping</Button>
<Button onClick={()=>{this.handleGo()}}>See Your Cart</Button>
</Modal.Footer>
</Modal>
<Modal isOpen={this.state.activeModal === 'selectQuantity'} id="#selectQuantity" show={this.state.showError} onHide={()=>{this.handleModalError()}}>
<Modal.Header closeButton> My heading</Modal.Header>
<Modal.Body> Please choose quantity first!</Modal.Body>
</Modal>
What I am trying to call different modal from this function if quantity is empty then call modal selectQuantity if quantity is chosen then call second modal addedToCart.
handleSubmit(e,id)
{
e.preventDefault();
if(!this.state.qty) {
$('#selectQuantity').openModal();
}
else {
axios.post('add',{qty:this.state.qty,
id:id})
$('#addedToCart').openModal();
}
}
Anyone has idea how to do this?
I think:
handleSubmit(e, id) {
...
if(!this.state.qty) {
this.setState({ activeModal: "selectQuantity" })
} else {
...
this.setState({ activeModal: "addedToCart" })
}
}

Unable to use bootstrap-react modal in stateless function

What I want to do is add bootstrap-react modal and fire it from a stateless function. All the examples I can find requires changing the "show" in the state of component, but since Im not using af component I don't really have an idea how to do it.
https://react-bootstrap.github.io/components/modal/
https://react-bootstrap.github.io/components/modal/
You need state somewhere to show the modal. You can use hooks to do it in functional (not really "stateless") component using useState.
function App() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="primary" onClick={() => setOpen(true)}>
Launch demo modal
</Button>
<Modal show={open} onHide={() => setOpen(false)}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={() => setOpen(false)}>
Close
</Button>
<Button variant="primary" onClick={() => setOpen(false)}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
codesandbox: https://codesandbox.io/embed/z2ky5l128l
If you don't want to do it then you need to pass prop from component that is higher in tree, like:
class App extends React.Component {
state = {
open: true,
}
render() {
return <ModalComponent open={open} hide={() => this.setState({open: false})} />
}
}
function ModalComponent = ({open, hide}) => (
<Modal show={open} onHide={hide}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={hide}>
Close
</Button>
</Modal.Footer>
</Modal>
)
just pass visible state from parrent like below
class parent extends Component {
state = {
modalVisibility : false
}
handleModalVisibility = (action)=> this.setState({modalVisibility : action})
return (
<div>
<button onClick={this.handleModalVisibility.bind(this,true)} >Show Modal</button>
//use this props to show or cancel the modal
<ModalComponent visibility ={this.state.modalVisibility} handleModal={this.handleModalVisibility} />
</div>
)
}
I guess you can do that with useState
https://reactjs.org/docs/hooks-state.html

How do I pass the parameter in every call to a react.js class method to a modal contained inside it?

I have two classes. In the render() method of Timeslots, when I pass the parameter to this.colhour and use it in an instance of TsModal, modalid is always assigned as '11:00-11:30'. How do I assign modalid as the unique parameter that is passed in the function call?
class Timeslots extends Component {
popoverHoverFocus() {
return (
<Popover id="popover-trigger-hover-focus" title="Table status">
<strong>P1 -> </strong> <br />
<strong>P2 -> </strong> <br />
<strong>S1 -> </strong> <br />
<strong>S2 -> </strong> <br />
<strong>S3 -> </strong> <br />
</Popover>
);
}
colhour(time) {
return (
<Col className='halfhour' xs={4} md={1}>
<TsModal modalid = {time} show={this.state.show} onhide={this.handleClose} onclick={this.handleClose} />
<OverlayTrigger overlay={this.popoverHoverFocus()}>
<Button bsStyle="primary" bsSize="small" onClick={this.handleShow}>
{time}
</Button>
</OverlayTrigger>
</Col>
);
}
render() {
return (
<Grid>
<br></br>
<Row className="timeslot">
{this.colhour('10:00-10:30')}
{this.colhour('10:30-11:00')}
{this.colhour('11:00-11:30')}
</Row>
</Grid>
);
}
}
class TsModal extends React.Component {
render() {
return (
<Modal show={this.props.show} onHide={this.props.onhide}>
<Modal.Header closeButton>
<Modal.Title>Book Tables</Modal.Title>
</Modal.Header>
<Modal.Body>
<hr />
<Button bsStyle="primary" bsSize="small" href={'http://localhost:4000/?id=' + this.props.modalid}>Pool table 1</Button>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.props.onclick}>Close</Button>
</Modal.Footer>
</Modal>
);
}
}
Well, I found a way to pass the value of the button that is clicked to the TsModal instance.
I made a handler function handleButPush and passed keeptimeto it. Then I stored that value in a state buttonPush and passed the state value to the TsModal instance. By this, modalid is assigned the different keeptime value everytime.
this.state = {
show: false,
buttonPush: 'invalid',
list : [],
popoverlist : [{status: "Available"},{status: "Available"},{status:"Available"},{status: "Available"},{status:"Available"}]
};
handleButPush(val) {
this.setState({ buttonpush: val });
}
colhour(keeptime,butdisable) {
return(
<Col className='halfhour' xs={4} md={1}>
<TsModal modalid = {this.state.buttonpush} show={this.state.show} onhide={this.handleClose} onclick={this.handleClose} />
<OverlayTrigger overlay = {() => {this.popoverHoverFocus({keeptime},{butdisable})} } >
<Button bsStyle="primary" bsSize="small" onClick={() => { this.handleShow(); this.handleButPush({keeptime}); }}>
{keeptime}
</Button>
</OverlayTrigger>
</Col>
);
}

React-bootstrap Modal component opens/closes all modals when I map through a list

New to programming so I'm sorry if I'm not wording this correctly. I'm using a .map to render and list every single item on an array. For each item, I want the modal to open/close only the specific modal corresponding to each item in the array. However, when I click on the button to open the modal, every single one opens and closes. I believe this is because the modals are all set to an on/off button together. How can I set it it (with the .map value.id or something) so that only the specific modal opens and closes?
class DrinkMenu extends Component {
constructor(props, context) {
super(props, context);
this.state = {
show: false
};
this.handleHide = this.handleHide.bind(this);
}
handleHide() {
this.setState({ show: false });
}
async componentDidMount() {
let res = await axios.get('/getAllDrinks')
this.props.updateDrinkMenu(res.data)
}
async addToCart(drinkObj) {
let res = await axios.post('/addToCart', drinkObj)
console.log(`Added ${drinkObj.name} to order.`)
}
render() {
let drinkList = this.props.drinkMenu.map((drink) => {
return (
<div key={drink.id}>
<h5>{drink.name}</h5>
<h6>${drink.price}</h6>
<span
onClick={() => this.setState({ show: true })}
>
<strong>More Info</strong>
<br />
<button onClick={() => this.addToCart(drink)}>Add to Order</button>
</span>
<Modal
show={this.state.show}
onHide={this.handleHide}
container={this}
aria-labelledby="contained-modal-title"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title">
{drink.name}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>{drink.sub_category} | ABV {drink.abv}% | {drink.origin}</p>
<Col xs={6} md={4}>
<Image className="drink-logo" src={drink.logo} thumbnail />
</Col>
<p className="drink-description"><strong>Description</strong><br />{drink.description}</p>
<p href={drink.website}>Website</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.handleHide}>Close</Button>
</Modal.Footer>
</Modal>
</div>
)
})
return (
<div>
<h2>Drink Menu</h2>
<div>
{drinkList}
</div>
</div>
)
}
}
From the code you have shared, I see that you are handling all the Model with the same state value, i.e. show. This is causing all the state for all the Models to be true hence all of them as shown.
To solve this, you can extract your whole component in a new React class which has just the functionality to show Modal as per the independent state. So your new React component will look something like this:
class DrinkComponent extends React.Component {
constructor(props) {
super(props);
this.handleHide = this.handleHide.bind(this);
this.state = {
show: false,
}
}
handleHide() {
this.setState({ show: false });
}
render() {
const { drink } = this.props;
return (<div key={drink.id}>
<h5>{drink.name}</h5>
<h6>${drink.price}</h6>
<span
onClick={() => this.setState({ show: true })}
>
<strong>More Info</strong>
<br />
<button onClick={() => this.props.addToCart(drink)}>Add to Order</button>
</span>
<Modal
show={this.state.show}
onHide={this.handleHide}
container={this}
aria-labelledby="contained-modal-title"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title">
{drink.name}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>{drink.sub_category} | ABV {drink.abv}% | {drink.origin}</p>
<Col xs={6} md={4}>
<Image className="drink-logo" src={drink.logo} thumbnail />
</Col>
<p className="drink-description"><strong>Description</strong><br />{drink.description}</p>
<p href={drink.website}>Website</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.handleHide}>Close</Button>
</Modal.Footer>
</Modal>
</div>);
}
}
In this case, each DrinkComponent will have its independent state of showing and hiding of the model. Now we have to just modify your existing render function in DrinkMenu, to display DrinkComponent. So your render function will look something like this:
render() {
let drinkList = this.props.drinkMenu.map((drink) => (<DrinkComponent drink={drink} addToCart={this.addToCart}/>));
return (
<div>
<h2>Drink Menu</h2>
<div>
{drinkList}
</div>
</div>
)
}
Also you can remove the show state from DrinkMenu as it wont be needed there.
Hope it helps.

onClick Rendering is not happening ReactJs

I am creating a web application with react.js also using react-bootstrap.
What I want to accomplish is when user click on button then modal will appear but that is not happening.
Button code
<div className="rightButtons">
<button name="updateItem" className="btn btn-primary" onClick={() => { this.onUpdateItem(this.props.selectedAppTypeId)}} >Update Item</button>
</div>
function which will be called.
onUpdateItem = (id) => {
return (
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>One fine body...</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
Any help would be great help. Thanks.
You are returning HTML into your onClick handler, and not into the Component's render method. If you want to show HTML content after an onClick, you need to actually return those HTML elements within the actual render. Try this:
class Component extends React.Component {
state = {
showModal: false
}
renderModal = () => {
return (
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>One fine body...</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
render() {
return(
<div>
<button onClick={() => this.setState({showModal:true})}> Show </button>
{this.state.showModal && this.renderModal()}
</div>
)
}
}
Edit: You can also export that entire Modal return statement into its own component, and conditionally render the component when the showModal state is true.
const ModalComponent = (props) => {
return(
<div className="static-modal">
<Modal.Dialog>
<Modal.Header>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>One fine body...</Modal.Body>
<Modal.Footer>
<Button>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
)
}
class ParentComponent extends React.Component {
state = {
showModal: false
}
render(){
return(
<div>
<button onClick={() => this.setState({showModal:true})}>
Show Modal
</button>
{this.state.showModal && <ModalComponent id='0af141random'/>}
</div>
)
}
}
The problem that you have is that you're passing a react function component as an event handler; the return value of the function is a react component, but calling the function by itself won't mount that component in the DOM and display it.
A better way to make this happen might be to place your Modal component in your component hiearchy, and control whether it is shown by using a callback to change the state of a parent component.
Something like this:
class ParentComponent extends React.Component {
showModal() {
this.setState{
modalActive: true;
}
}
render() {
<div>
<Button onClick={showModal}>Show me the modal!</Button>
<Modal active={this.state.modalActive} />
</div>
}
}
const modalComponent = (props) => {
return (<div style={{ display: (props.isActive) ? "block" : "none "}}>
<h1>I'm a modal!</h1>
</div>)
}
I haven't checked, but I'm sure React Bootstrap has its own prop for displaying/hiding modals.
EDIT: Here's a code example from the react bootstrap documentation that shows it in use https://react-bootstrap.github.io/components/modal/#modals-live

Resources