Opening a Modal in React with an ID passed to the component - reactjs

I have an application which prompts a user to add an entry via a modal. However, I can't figure out how to call the modal from the function and neither can I figure out how to pass the id to the modal.
So far I've been able to get the two parts written up and compiled but not working together
'Add Entry' button
import React from 'react';
import '../../App.css'
import VideoModal from '../components/VideoModal'
function NewEntry ({event}){
return (
<span><i class="fa fa-plus-circle" aria-hidden="true"></i></span>
<VideoModal entry={event}
);
}
export default NewEntry;
Note that this doesn't call the modal component. I've attempted variations of onClick={this.closeModal} for the <I> tag to no avail, but this obviously won't work. And I've included the modal as a component.
I know, I know this isn't the right way of doing this, I just haven't yet found examples I can wrap my head around.
The Modal
import React, { Component } from "react";
import { Modal, Button } from "react-bootstrap";
import '../../App.css'
class VideoModal extends Component {
state = {
isOpen: false
};
openModal = () => this.setState({ isOpen: true });
closeModal = () => this.setState({ isOpen: false });
render() {
return (
<>
<Modal show={this.state.isOpen} onHide={this.closeModal}>
<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={this.closeModal}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
}
}
export default VideoModal;

First of all, the VideoModal tag is not closed, pay attention to it.
Then you can move the open/close logic outside the modal, inside NewEntry:
import React, { Component } from 'react';
import '../../App.css'
import VideoModal from '../components/VideoModal'
class NewEntry extends Component {
state = {
isModalOpen: false
};
openModal = () => this.setState({ isModalOpen: true });
closeModal = () => this.setState({ isModalOpen: false });
render() {
return (
<span onClick={() => this.openModal()}><i class="fa fa-plus-circle" aria-hidden="true"></i></span>
<VideoModal closeModal={() => this.closeModal()} isOpen={this.state.isOpen} />
);
}
}
export default NewEntry;
And use VideoModal as a pure component:
import React from "react";
import { Modal, Button } from "react-bootstrap";
import '../../App.css'
function VideoModal (props) {
const { isOpen, closeModal } = props;
return (
<>
<Modal show={isOpen} onHide={closeModal}>
<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={closeModal}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
}
export default VideoModal;

Related

React. Show Bootstrap modal in different component

I am trying to display a Bootstrap modal which is in a different component than the button which open the modal.
Header.js
import React, { useState } from "react";
import Search from "./Search";
function Header() {
const [showModal, setShowModal] = useState(false);
const handleShowModal = () => setShowModal(true);
return (
<header>
<ul>
<li>
<button className="btn" onClick={handleShowModal}>
Search
</button>
</li>
</ul>
<Search shoWChildModal={handleShowModal} />
</header>
);
}
export default Header;
Search.js
import React, { useState } from "react";
import Modal from 'react-bootstrap/Modal';
function Search(shoWChildModal) {
const [showModal, setShowModal] = useState(false);
const handleCloseModal = () => setShowModal(false);
return (
<Modal show={shoWChildModal} onHide={handleCloseModal}>
<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={handleCloseModal}>
Close
</button>
<button variant="primary" onClick={handleCloseModal}>
Save Changes
</button>
</Modal.Footer>
</Modal>
);
}
export default Search;
Actually the modal opens on page load. Would it be possible to open the modal with the onclick event of the button?

How implementing a modal with reactjs

i have a modal, but dont recognize their styles, what is the matter?, why dont recognize the styles? i need to import an other dependecy?
import React,{Component} from 'react'
import Modal from 'react-bootstrap/Modal'
import Button from 'react-bootstrap/Button';
class CustomModal extends Component{
constructor(props) {
super(props);
this.state = {
show: false
};
this.handleClose = this.handleClose.bind(this);
this.handleShow = this.handleShow.bind(this);
}
handleClose (){
this.setState({ show: false });
};
handleShow (){
this.setState({ show: true });
};
render() {
return(
<div>
<Button variant="primary" onClick={this.handleShow}>Update</Button>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Update</Modal.Title>
</Modal.Header>
<Modal.Body>...</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.handleClose}>Close</Button>
<Button variant="primary">Save</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default CustomModal;
i am using Button but my button never is painting
I simply changed the way you have imported the Components and it started working.
Changed the import to
import { Modal, Button } from "react-bootstrap";
From
import Modal from 'react-bootstrap/Modal'
import Button from 'react-bootstrap/Button';
Live demo here
https://codesandbox.io/s/react-bootstrap-x0ix0?fontsize=14&hidenavigation=1&theme=dark

Modal Component - How to include and open/close from another component

I'm just starting to learn React. I've got a modal component (that's basically a wrapper for react-bootstrap's Modal component). The idea is to have a "Feedback" modal that I can include in various places. This approach isn't working, and I don't know what I don't know :/
Below is a quick example of what I mean / how I'm trying to display my modal component
import React, { Component } from 'react'
import Modal from 'react-bootstrap/Modal'
import Button from "components/button/button"
export class BaseModal extends Component {
constructor(props) {
super(props);
this.state = { show: false };
}
toggleModal() {
this.setState({ show: !this.state.show })
}
render() {
if (!this.props.show) {
return null;
};
return (
<>
<Modal show={this.state.show}>
<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={this.toggleModal}>
Close
</Button>
<Button variant="primary" onClick={this.toggleModal}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
)
}
}
A simple page like this - clicking this button doesn't do anything (React dev tools show no BaseModal node in the vdom)
import React, { Component } from 'react'
import Button from "components/button/button"
import BaseModal from "components/modals/baseModal"
export class ButtonDocs extends Component {
render() {
<Button value="Open Modal" onClick={BaseModal.toggleModal} />
}
}
You can't just import a Component and then call a method on it, because you aren't actually rendering it anywhere.
What you need to do is render the Component, and then if you want to control the state of one component from another you need to "lift state up" and pass the state and any methods needed to the modal component as props. Something like this:
Modal Component
import React, { Component } from 'react'
import Modal from 'react-bootstrap/Modal'
import Button from "components/button/button"
export class BaseModal extends Component {
render() {
if (!this.props.show) {
return null;
};
return (
<>
<Modal show={this.state.show}>
<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={this.props.toggleModal}>
Close
</Button>
<Button variant="primary" onClick={this.props.toggleModal}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
)
}
}
Button Docs
import React, { Component } from 'react'
import Button from "components/button/button"
import BaseModal from "components/modals/baseModal"
export class ButtonDocs extends Component {
constructor(props) {
super(props);
this.state = { show: false };
}
toggleModal() {
this.setState({ show: !this.state.show })
}
render() {
<Button value="Open Modal" onClick={this.toggleModal} />
<BaseModal show={this.state.show} toggleModal={this.toggleModal} />
}
}

How to customize react-bootstrap modal

Suppose I have a modal like as follows and I would like it such that, when the modal is showing at that time I also want to work on the background.
In the following code, there is a textbox. I want to work with the textbox(or an audio) when the model is appearing.
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { Modal, Button } from 'react-bootstrap';
import './GenericModal.scss';
class GenericModal extends Component {
constructor(props, context) {
super(props, context);
this.state = {
showModal: false
};
this.open = this.open.bind(this);
this.close = this.close.bind(this);
}
open() {
this.setState({showModal: true});
}
close() {
this.setState({showModal: false});
}
render() {
return(
<div>
<div>I am a Bootstrap Modal</div>
<Button onClick={this.open}>Show Modal</Button>
<div>
<Modal className="modal-container" id="demo-class" ref={node => this.chart = node}
show={this.state.showModal}
onHide={this.close}
bsSize="small" backdrop={false}
>
<Modal.Header closeButton>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
One of fine body.........
</Modal.Body>
<Modal.Footer>
<Button onClick={this.close}>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal>
<Button onClick={this.open}>Show Modal</Button>
<input type="text" />
</div>
</div>
);
}
}
export default GenericModal;
I hope the below example flow addresses your requirement.
More form the comments in code.
i.e onClick calls wrapper function which has open method for modal together with your customizations.
import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { Modal, Button } from 'react-bootstrap';
import './GenericModal.scss';
class GenericModal extends Component {
constructor(props, context) {
super(props, context);
this.state = {
showModal: false
};
this.open = this.open.bind(this);
this.close = this.close.bind(this);
}
open() {
let _this = this;
this.setState({showModal: true}, function(){
//state is set, i.e modal is loaded in view
//here you can do whatever like stopping audio
//_this.stopAudio();
});
}
close() {
this.setState({showModal: false});
}
playSomeAudio(){
//playAudio();
}
stopAudio(){
//stop the audio
}
doSomethingBeforeOpen(){
var _this = this;
//do whatever you want before opening model. i.e palying audio
//1. in sync:
this.playSomeAudio(); //audio starts palying before modal starts triggered
//2. in async
setTimeOut(() => {_this.playSomeAudio()}, 1); //async by setTimeout, keep your own time
//Or any
this.open(); //opens modal
}
render() {
return(
<div>
<div>I am a Bootstrap Modal</div>
<Button onClick={this.doSomethingBeforeOpen.bind(this)}>Show Modal</Button>
<div>
<Modal className="modal-container" id="demo-class" ref={node => this.chart = node}
show={this.state.showModal}
onHide={this.close}
bsSize="small" backdrop={false}
>
<Modal.Header closeButton>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
One of fine body.........
</Modal.Body>
<Modal.Footer>
<Button onClick={this.close}>Close</Button>
<Button bsStyle="primary">Save changes</Button>
</Modal.Footer>
</Modal>
<Button onClick={this.doSomethingBeforeOpen.bind(this)}>Show Modal</Button>
<input type="text" />
</div>
</div>
);
}
}
export default GenericModal;

Testing React with Boostrap Modal on click

I've got this simple code from react bootstrap website...
import {Modal} from 'react-bootstrap';
import React from 'react';
export default class ModalExperiment extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
}
}
render(){
let openModal = () => this.setState({open: true});
let closeModal = () => this.setState({ open: false });
return (
<div>
<button type='button' onClick={openModal} className='launch'>Launch modal</button>
<Modal
show={this.state.open}
onHide={closeModal}
aria-labelledby="ModalHeader" className='modalClass'
>
<Modal.Header closeButton>
<Modal.Title id='ModalHeader'>A Title Goes here</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Some Content here</p>
</Modal.Body>
<Modal.Footer>
// If you don't have anything fancy to do you can use
// the convenient `Dismiss` component, it will
// trigger `onHide` when clicked
<Modal.Dismiss className='dismiss btn btn-default'>Cancel</Modal.Dismiss>
// Or you can create your own dismiss buttons
<button className='btn btn-primary' onClick={closeModal}>
Close
</button>
</Modal.Footer>
</Modal>
</div>
)
}
}
And here is my test... simple I want to click the launch button, verify the Modal opens, and then click on the Cancel button to verify the Modal is no longer opened.
'use strict';
import React from 'react';
import ReactAddons from 'react/addons';
import {Modal} from 'react-bootstrap';
import ModalExperiment from '../ModalExperiment';
import ReactDOM from 'react-dom';
let TestUtils = React.addons.TestUtils;
fdescribe('ModalExperimentFunctional', function() {
let page;
fit("click the ok button should open the modal", () => {
page = TestUtils.renderIntoDocument(<ModalExperiment/>);
let launch = TestUtils.findRenderedDOMComponentWithClass(page, 'launch');
let openButton = React.findDOMNode(launch);
openButton.click(); // work till here
//let modal = TestUtils.findRenderedComponentWithType(page, Modal);// this managed to find Modal type
let modal = TestUtils.findRenderedDOMComponentWithClass(page, 'modalClass'); // this fails to find the modalClass..
});
});
How can I find the Cancel button please? I tried all sort of things, nothing seems to have worked for me.
I finally got it working using jquery selector..
import {Modal} from 'react-bootstrap';
import React from 'react';
export default class ModalExperiment extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false
}
}
openModal() {
this.setState({open: true});
}
closeModal() {
this.setState({open: false });
}
render(){
return (
<div>
<button type='button' onClick={this.openModal.bind(this)} className='openButton'>Launch modal</button>
{this.state.open?
<Modal
show={this.state.open}
onHide={this.closeModal.bind(this)}
aria-labelledby="ModalHeader" className='modalClass'
>
<Modal.Header closeButton>
<Modal.Title id='ModalHeader'>A Title Goes here</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Some Content here</p>
</Modal.Body>
<Modal.Footer>
<button className='closeButton btn btn-primary' onClick={this.closeModal.bind(this)}>
Close
</button>
</Modal.Footer>
</Modal> : ''}
</div>
)
}
}
And here is the test...
'use strict';
import React from 'react';
import ReactAddons from 'react/addons';
import {Modal} from 'react-bootstrap';
import ModalExperiment from '../ModalExperiment';
import $ from 'jquery';
let TestUtils = React.addons.TestUtils;
describe('ModalExperimentFunctional', function() {
let page;
beforeEach(() => {
document.body.innerHTML = '';
page = TestUtils.renderIntoDocument(<ModalExperiment/>);
});
fit("click the ok button should open the modal", () => {
expect($('.closeButton').length).toBe(0);
let openButton = React.findDOMNode(TestUtils.findRenderedDOMComponentWithClass(page, 'openButton'));
TestUtils.Simulate.click(openButton);
expect($('.closeButton').length).toBe(1);
$('.closeButton').click();
expect($('.closeButton').length).toBe(0);
});
});
In test use:
const component = ReactTestUtils.renderIntoDocument(<Modal />);
ReactTestUtils.Simulate.click(document.body.getElementsByClassName("close")[0]);

Resources