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.
Related
Requirement: Create a plugin that should have a button in the toolbar, On click should open a popup window which is a react component defined outside the plugin component.
export default class OpenPopup extends Plugin {
init() {
const editor = this.editor;
editor.ui.componentFactory.add('openPopup', locale => {
const view = new ButtonView(locale);
view.set({
label: 'Open Popup model',
icon: popupImage,
tooltip: true
});
// Callback executed once the button is clicked.
view.on('execute', () => {
});
return view;
});
}
}
Popup code
import React, { useEffect, useState } from 'react';
import PropTypes from "prop-types";
import { Modal } from 'react-bootstrap';
const Popup= ({ show = false }) => {
return (
<Modal
size="xl"
show={show}
dialogClassName="add-media-modal"
onHide={()=> {show = false}}
>
<Modal.Header>
<Modal.Title id="contained-modal-title-vcenter">
Add Media
</Modal.Title>
<button type="button" className="btn btn-primary btn-sm" onClick={handleCloseModal}>X</button>
</Modal.Header>
<Modal.Body>
</Modal.Body>
<Modal.Footer>
<button
type="button" className="btn btn-primary btn-sm"
>
Add
</button>
</Modal.Footer>
</Modal>
)
}
Popup.propTypes = {
show: PropTypes.bool
};
export default Popup
I was looking for various options or solutions to the above requirement.
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)} />
</>
)
}
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>
everyone, I want to add edit functionality into my project but I didn't understand how I can add that so can you please help me and I want to open my form on a modal on a button click "When they click on the button the modal will be open with the form" "when clicking on the edit button again modal will open with predefined values and when I edit the fields the table will be update "
here is my code
App.js
import React, { Component } from "react";
//import ReactDOM from "react-dom";
import Form from "./Form";
//import Modal from 'react-modal';
import { makeStyles } from '#material-ui/core/styles';
import Table from '#material-ui/core/Table';
import TableBody from '#material-ui/core/TableBody';
import TableCell from '#material-ui/core/TableCell';
import TableContainer from '#material-ui/core/TableContainer';
import TableHead from '#material-ui/core/TableHead';
import TableRow from '#material-ui/core/TableRow';
import Paper from '#material-ui/core/Paper';
import Button from '#material-ui/core/Button';
import "./styles.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
people: []
};
this.addPerson = this.addPerson.bind(this);
this.deletePerson = this.deletePerson.bind(this);
}
addPerson(name, email, phone) {
this.setState(prevState => ({
people: [...prevState.people, { name, email, phone }]
}));
}
componentDidMount() {
this.getPeople();
}
getPeople() {
fetch("https://jsonplaceholder.typicode.com/users")
.then(response => response.json())
.then(response => this.setState({ people: response }))
.catch(error => console.log(error));
}
deletePerson(email) {
return () => {
this.setState(prevState => ({
people: prevState.people.filter(person => person.email !== email)
}));
};
}
editPerson(email) {
return () => {
this.setState({email})
}
}
render() {
console.log(this.state);
return (
<div className="App">
<Form addPerson={this.addPerson} />
<TableContainer component={Paper}>
<TableHead>
<TableRow>
<TableCell>LP</TableCell>
<TableCell>USER</TableCell>
<TableCell>EMAIL</TableCell>
<TableCell>Phone</TableCell>
<TableCell>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{this.state.people.map((person, index) => {
return (
<TableRow key={person.email}>
<TableCell>{index + 1}</TableCell>
<TableCell>{person.name}</TableCell>
<TableCell>{person.email}</TableCell>
<TableCell>{person.phone}</TableCell>
<TableCell>
<Button variant="contained" color="secondary" onClick={this.editPerson(person.email)}>
Edit
</Button>
</TableCell>
<TableCell>
<Button variant="contained" color="secondary" onClick={this.deletePerson(person.email)}>
Delete
</Button>
</TableCell>
</TableRow>
);
})}
</TableBody>
</TableContainer>
</div>
);
}
}
export default App;
Form.js
import React, { Component, useState } from "react";
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
import Modal from './Modal'
const validEmailRegex = RegExp(
/^(([^<>()\[\]\.,;:\s#\"]+(\.[^<>()\[\]\.,;:\s#\"]+)*)|(\".+\"))#(([^<>()[\]\.,;:\s#\"]+\.)+[^<>()[\]\.,;:\s#\"]{2,})$/i
);
class Form extends Component {
constructor() {
super();
this.formSubmit = this.formSubmit.bind(this);
this.state = {
name: null,
email: null,
phone: null,
errors: {
name: '',
email: '',
phone: '',
}
};
}
handleChange = (event) => {
event.preventDefault();
const { name, value } = event.target;
let errors = this.state.errors;
switch (name) {
case 'name':
errors.name =
value.length < 5
? 'Name must be 5 characters long!'
: '';
break;
case 'email':
errors.email =
validEmailRegex.test(value)
? ''
: 'Email is not valid!';
break;
case 'phone':
errors.phone =
value.length < 8
? 'Password must be 8 characters long!'
: '';
break;
default:
break;
}
this.setState({ errors, [name]: value }, () => {
console.log(errors)
})
}
formSubmit(event) {
event.preventDefault();
const form = event.target;
const email = form.elements["email"].value;
const name = form.elements["name"].value;
const phone = form.elements["phone"].value;
this.props.addPerson(name, email, phone);
form.reset();
}
state = { show: false };
showModal = () => {
this.setState({ show: true });
};
hideModal = () => {
this.setState({ show: false });
};
render() {
return (
<div>
<Modal />
<form onSubmit={this.formSubmit}>
<TextField onChange={this.handleChange} id="name" type="text" defaultValue="" placeholder="Name..." />
<br />
<TextField onChange={this.handleChange} id="email" type="text" defaultValue="" placeholder="Email..." />
<br />
<TextField onChange={this.handleChange} id="phone" type="number" defaultValue="" placeholder="Phone Number" />
<br />
<br />
<Button type="submit" value="submit" variant="contained" color="primary" onSubmit={this.handleChange}> Submit </Button>
</form>
</div>
);
}
}
export default Form;
Modal.js
import React, { useState } from 'react';
import { Modal } from 'react-bootstrap';
import Button from '#material-ui/core/Button';
import TextField from '#material-ui/core/TextField';
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="contained" color="primary" onClick={handleShow}>
Demo modal
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Body closeButton>
Form
</Modal.Body>
<Modal.Footer>
<Button variant="contained" color="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="contained" color="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
export default Example;
You want to open modal and the modal has a form inside it, right?
So you'll import Modal.js file in App.js
like that import Modal from ./Modal.js
And inside the initial state add
this.state = {
people: [],
showModal: false
};
Create a function to close model on press close button that inside Modal
const handleClose = () => this.setState({showModal: false})
And use the component under this line <div className="App">
you'll write:
<Modal show={this.state.showModal} email={this.state.email} close={this.handleClose}/>
Inside this function editPerson you must write this code without return
write:
this.setState({email, showModal: true})
ِAfter that you'll open Model.js file and import Form from Form.js file
and change this line
<Modal show={show} onHide={handleClose}>
to this:
<Modal show={props.show} onHide={props.handleClose}>
yeah and before I forget you should change this function (component)
function Example() to receive props so it'll be
function Example(props) {
...
}
Please help me to sort out this problem I want to open modal after clicking n card. I have use button and under that, I use card.
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button } from 'react-bootstrap';
import CardDesing from './CardDesing'
import Modals from './Modal';
class App extends React.Component {
render() {
return (
<Button onClick={this.onCardClick} className="unstyled-button">
<CardDesing />
</Button>
);
}
onCardClick = () => {
console.log("hello");
return (
<Modals />
);
}
}
ReactDOM.render(<App />, document.querySelector("#root"))
You can render your model conditionally. if button is clicked then we are showing model
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button } from 'react-bootstrap';
import CardDesing from './CardDesing'
import Modals from './Modal';
class App extends React.Component {
state = {
isClicked : false // button clicked or not
}
// set new state to your isClicked
onCardClick = () => {
this.setState({ isClicked : !this.state.isClicked })
}
render() {
return (
<>
<Button onClick={this.onCardClick} className="unstyled-button">
<CardDesing />
</Button>
{
this.state.isClicked ? <Modals /> : ''
}
</>
);
}
}
ReactDOM.render(<App />, document.querySelector("#root"))
Render modal and just show it on click:
state = {
show: false
}
render() {
return (
<>
<Button onClick={this.onCardClick} className="unstyled-button">
<CardDesing />
</Button>
{ this.state.show && <Modals /> || '' }
</>
);
}
onCardClick = () => {
this.setState({ show: true })
}
According to react-bootstrap docs
You should use the property: show: When true The modal will show itself.
Example:
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<div>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
<Modal show={show} onHide={handleClose}>
{/* */}
</Modal>
</div>
);
}