how to show react bootstrap modal inside the function - javascript

I am using react bootstrap modal popup. when user submit form, I need to modal show popup,
This is my modal (SaveConfirmationModal )
import { Button, Modal} from "react-bootstrap";
function SaveConfirmationModal(props) {
return (
<div>
<Modal {...props} size="lg">
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
do u want to save ?
</Modal.Title>
</Modal.Header>
<Modal.Body>
<button>YEs </button>
<button>No</button>
</Modal.Body>
</Modal>
</div>
);
}
export default SaveConfirmationModal;
this is my invoice page save function. I imported my modal in to the invoice page.
import SaveConfirmationModal from "components/createinvoice/SaveConfirmationModal";
const loadPopup= (data) => {
showmodal;
if(yes){
saveForm();
}
else{
close modal
}
}
const saveForm= (data){
my save function
}
my save button in the invoice page
<button onClick={loadPopup}> Save </button>
This is the very little sample to demonstrate my issue. If you can please help me to show this confirmation box. thanks

In the component where you use your SaveConfirmationModal, you can use state Hooks, like this:
import React, {useState} from 'react';
...
const [showModal, setShowModal] = useState(false);
const loadPopup = () => {
setShowModal(true);
};
And you need to change the state to false when the modal is dismissed:
<SaveConfirmationModal show={showModal} onHide={() => setShowModal(false)}

You can call a function from a prop on button click like below.
import { Button, Modal} from "react-bootstrap";
function SaveConfirmationModal(props) {
return (
<div>
<Modal {...props} size="lg">
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
do u want to save ?
</Modal.Title>
</Modal.Header>
<Modal.Body>
<button onClick={props.onYes}>YEs </button>
<button onClick={props.onNo}>No</button>
</Modal.Body>
</Modal>
</div>
);
}
export default SaveConfirmationModal;
Then in your invoice page create a state for showing a modal and pass the props like below.
import { useState } from 'react'
import SaveConfirmationModal from "components/createinvoice/SaveConfirmationModal";
const InvoicePage = () => {
const [showModal, setShowModal] = useState(false);
const saveForm = (data) {
// my save function
}
return (
<>
<button onClick={() => setShowModal(true)}> Save </button>
<SaveConfirmationModal show={showModal} onYes={() => saveForm(data)} onNow={() => setShowModal(false)} />
</>
)
}

Related

React Bootstrap Modal not working on submit Button

I am looking to send the value from the Form.Control to the button so I can do some logic but I cannot seem to get this value from the input. I tried using reft but I cant use refs in a functional component, so I'm using the textInput. Please help, been stuck for 3 days. thx
import React from "react";
import { Modal, Form, Row, Col, Button } from "react-bootstrap";
import "./Login.css";
export const ForgotPassword = (props) => {
let textInput = null;
const handleClick = () => {
console.log("i am here", textInput.focus());
};
return (
<>
<Modal
{...props}
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Forgot Password
</Modal.Title>
</Modal.Header>
<Modal.Body className="show-grid">
<Form.Label>Please enter your Employee ID.</Form.Label>
<Row>
<Col className="lm-qus" md={5}>
Employee ID:
</Col>
<Col md={7}>
<Form.Control
type="text"
required
name="answer"
placeholder=""
ref={(input) => {
textInput = input;
}}
/>
</Col>
</Row>
</Modal.Body>
<Modal.Footer>
<Button onClick={props.onHide}>Cancel</Button>
<Button onClick={handleClick} type="submit">
Continue
</Button>
</Modal.Footer>
</Modal>
</>
);
};
This is not a modal specific problem. Make your Form.Control a controlled input by providing "value" attribute. Define state and set this state on change event of the input. You can then access this state everywhere, including the button:
const [value, setValue] = React.useState("");
const handleChange = (event) => setValue(event.target.value);
const handleClick = () => alert(value);
https://codesandbox.io/s/objective-pond-rs8r9f

How to open Modal from another component in hooks?

In a React project, I have the requirement of opening Modal from another component. I found suggested questions from StackOverflow but, not yet convinced. As I need to make the Modal component reusable across all components. See the code below for reference
Homepage.js
const HomePage = () => {
return (
<>
<button onClick={() => setLoginModalShow(true)}>Open Modal</button>
</>
);
};
I created the below file to export other files too, and make it useful in other components
commonLogin.js
import LoginModal from "./LoginModal";
export const setLoginModalShow = (props) => {
console.log("PROPS", props);
return <LoginModal showModal={props} />;
};
And here is the Modal component
const LoginModal = (props) => {
const [loginModalShow, setLoginModalShow] = useState(props.showModal);
console.log("PROPS in MODAL", props);
return (
<>
<Modal
show={loginModalShow}
onHide={setLoginModalShow}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">Logout</Modal.Title>
</Modal.Header>
<Modal.Body>
<h4>Are you sure to Logout?</h4>
</Modal.Body>
<Modal.Footer>
<Button onClick={() => setLoginModalShow(false)}>Cancel</Button>
</Modal.Footer>
</Modal>
</>
);
};
Please refer to the code sandbox link: https://codesandbox.io/s/nameless-cdn-70zuq.
After you visit the page click on the 'Open Modal' button
You want to control the show/hide from the parent component
const HomePage = () => {
const [showLogin, setShowLogin] = useState(false);
return (
<>
<button onClick={() => setShowLogin(true)}>Open Modal</button>
<LoginModal show={showLogin} close={() => setShowLogin(false)} />
</>
);
};
<Modal
show={props.show}
cancel={props.close}
...
Here is a working example:
https://codesandbox.io/s/nice-euclid-d0dw0

React-Bootstrap modal not closing. Error: Cannot update a component (`OnboardPage`) while rendering a different component

I've seen a few other questions with the same error but they don't seem to solve my issue.
I have a react-bootstrap modal that im trying to open from a button inside a child component but I get the following error.
This is the parent component:
OnboardPage.jsx
import React from 'react'
import { Row } from 'react-bootstrap'
import { PersonalDetails } from './personalDetails'
import { EmailVerification } from './emailVerification'
import { Form } from './form'
import { FAQs } from './faq'
import { LeftCol, RightCol } from './styles'
import { Modal, Button } from 'react-bootstrap'
const OnboardPage = props => {
const [show, setShow] = React.useState(false);
const handleClose = (showValue) => setShow(false);
const handleShow = (showValue) => setShow(true);
return (
<Row>
<LeftCol md={8}>
<PersonalDetails parentShowFn={handleShow}/>
<Form />
</LeftCol>
<RightCol md={4}>
<EmailVerification />
<FAQs />
</RightCol>
<Modal show={show} onHide={handleClose}>
<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={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Row>
)
}
export default OnboardPage
Child Component:
Personaldetails.jsx
import React from 'react'
import { colors } from '../../../../res'
import { TitleText, CommonText, SubHeadingText } from '../../../commons/freelancer/texts'
import { Container, TitleRow, DetailsRow, DetailsItem, EditBtn } from './personalDetailsStyles'
import { Modal, Button } from 'react-bootstrap'
// import EditDetailsModal from './EditDetailsModal'
const PersonalDetails = ({parentShowFn}) => {
return (
<Container>
<TitleRow>
<TitleText>Personal Details</TitleText>
<EditBtn onClick={parentShowFn()}>Edit</EditBtn>
</TitleRow>
</Container>
)
}
export default PersonalDetails
I've seen the stack trace and i believe the problem lies here:
But I can't figure out what it is :/
There is something wrong with the Edit Button onClick prop
<Button onClick={parentShowFn()}>Edit</Button>
What this does is: on each render of PersonalDetails, this will just set the state for the show state back in OnboardPageto true, therefore when the Modal onHide event is fired, state updates will cause re-renders, PersonalDetails will be re-rendered and therefore set the state of show to true again due to the above code
Furthermore, handleShow does not return anything therefore subsequent clicks on the Edit Button will not do anything (i.e., onClick={undefined}).
I suggest you refactor the onClick prop value to return a function
<Button onClick={()=>parentShowFn()}>Edit</Button>

Conditonal rendering REACT modal component

I have a view modal component (ViewModal.js)
import React from 'react'
import { Button, Modal } from 'react-bootstrap';
import './Modal.css';
class ViewModal extends React.Component {
constructor() {
super();
this.state = {
}
}
handleModalShowHide() {
this.setState({ showHide: !this.state.showHide })
}
render() {
return (
<div>
<Button variant="success" onClick={() => this.handleModalShowHide()}>
Write a review
</Button>
<Modal show={this.state.showHide}>
<Modal.Header closeButton onClick={() => this.handleModalShowHide()}>
<Modal.Title>Add your review</Modal.Title>
</Modal.Header>
<Modal.Body>
ModalBody
</Modal.Body>
<Modal.Footer>
<Button variant="outline-secondary" onClick={() => this.handleModalShowHide()}>
Close
</Button>
<Button variant="outline-success" onClick={() => this.handleModalShowHide()}>
Save Review
</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
export default ViewModal;
I import this in another functional component called viewcard.js
The logic of viewcard.js is as follows
import React from 'react';
import ViewModal from './ViewModal';
import Card from 'Card';
function handleClick(){
console.log('in handle');
}
const viewcard = () => {
return (
<p onClick={() => handleClick()}/>
Some text in paragraph
</p>
);
}
export default viewcard;
The Card component displays some text on the screen.
What I am trying to achieve is when a user clicks on that text, I want to show the modal.
Currently If I render the modal inside viewcard, by calling it, It will show a button based on this line of logic
<Button variant="success" onClick={() => this.handleModalShowHide()}>
Write a review
</Button>
I want to remove the button and have the same behaviour happen when the user clicks on the text in viewcard.js
ViewCard component:-
import React, {useState} from 'react';
import ViewModal from './ViewModal';
import Card from 'Card';
const ViewCard = () => {
const [showModal, setShowModal] = useState(false);
function handleClick(){
setShowModal(!showModal)
}
return (
<Card onClick={() => handleClick()}/>
{showModal && <ViewModal hideBtn={true} showModal={true} />}
);
}
export default ViewCard;
ViewModal Component:
import React from 'react'
import { Button, Modal } from 'react-bootstrap';
import './Modal.css';
class ViewModal extends React.Component {
constructor() {
super();
this.state = {
showHide: this.props.showModal ? true : false
}
}
handleModalShowHide() {
this.setState({ showHide: !this.state.showHide })
}
render() {
return (
<div>
{this.props.hideBtn ? null : <Button variant="success" onClick={() => this.handleModalShowHide()}>
Write a review
</Button>}
<Modal show={this.state.showHide}>
<Modal.Header closeButton onClick={() => this.handleModalShowHide()}>
<Modal.Title>Add your review</Modal.Title>
</Modal.Header>
<Modal.Body>
ModalBody
</Modal.Body>
<Modal.Footer>
<Button variant="outline-secondary" onClick={() => this.handleModalShowHide()}>
Close
</Button>
<Button variant="outline-success" onClick={() => this.handleModalShowHide()}>
Save Review
</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
export default ViewModal;
But you should always create a separate modal component.

TypeScript React Invalid Hook Call Error ("Error: Invalid hook call.")

I tried asking a question earlier but realized it was a bit all over the place so no one could really understand it properly. So here's a more clarified attempt.
I am currently working on a CRUD web project that allows the user to edit, view and create more users which is then displayed on a table.
I have been using react-bootstrap's components so decided to use the Modal component provided. (https://react-bootstrap.netlify.com/components/modal/#modals-live)
It was successfully working without any errors when I just called and used the component within App.tsx as follows:
const App: React.FC = () => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div className="App">
<NavBar/>
<Jumbotron fluid className="userJumbotron">
<Container>
<h1>Manage Users</h1>
<Button variant="outline-dark" onClick={handleShow}>Add new user</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add User</Modal.Title>
</Modal.Header>
<Modal.Body><NewUserForm/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
But I think realized that I'll need more than 1 modal component for my program and decided to make the modal component section into my own component that I can reuse as many times as I want and customize as I want within the App.tsx
So I decided to make a NewModal.tsx component that has the bootstrap modal component and button pre-made meaning I'd only have to call one line () rather than a whole chunk. the NewModal.tsx code is as follows:
export default class NewModal extends Component<any> {
constructor (props: any){
super(props)
this.state={
show:false
}
}
render() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<h1>Manage Users</h1>
<Button variant="outline-dark" onClick={handleShow}>Add new user</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add User</Modal.Title>
</Modal.Header>
<Modal.Body><NewUserForm/></Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
I am getting the following error from this code.
What is the cause for this error?
You can't use hooks inside class components, you need to change it to be a function based component, which can look something like this:
const NewModal = () => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<h1>Manage Users</h1>
<Button variant="outline-dark" onClick={handleShow}>
Add new user
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add User</Modal.Title>
</Modal.Header>
<Modal.Body>
<NewUserForm />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
export default NewModal;

Categories