Bootstrap modal in React.js - javascript

I need to open a Bootstrap Modal from clicking on a button in a Bootstrap navbar and other places (to show data for a component instance, ie. providing "editing" functionality), but I don't know how to accomplish this. Here is my code:
EDIT: Code updated.
ApplicationContainer = React.createClass({
render: function() {
return (
<div className="container-fluid">
<NavBar />
<div className="row">
<div className="col-md-2">
<ScheduleEntryList />
</div>
<div className="col-md-10">
</div>
</div>
<ScheduleEntryModal />
</div>
);
}
});
NavBar = React.createClass({
render: function() {
return (
<nav className="navbar navbar-default navbar-fixed-top">
<div className="container-fluid">
<div className="navbar-header">
<a className="navbar-brand" href="#">
<span className="glyphicon glyphicon-eye-open"></span>
</a>
</div>
<form className="navbar-form navbar-left">
<button className="btn btn-primary" type="button" data-toggle="modal" data-target="#scheduleentry-modal">
<span className="glyphicon glyphicon-plus">
</span>
</button>
</form>
<ul className="nav navbar-nav navbar-right">
<li><span className="glyphicon glyphicon-user"></span> Username</li>
</ul>
</div>
</nav>
);
}
});
ScheduleEntryList = React.createClass({
getInitialState: function() {
return {data: []}
},
loadData: function() {
$.ajax({
url: "/api/tasks",
dataType: "json",
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, error) {
console.error("/api/tasks", status, error.toString());
}.bind(this)
});
},
componentWillMount: function() {
this.loadData();
setInterval(this.loadData, 20000);
},
render: function() {
items = this.state.data.map(function(item) {
return <ScheduleEntryListItem item={item}></ScheduleEntryListItem>;
});
return (
<div className="list-group">
<a className="list-group-item active">
<h5 className="list-group-item-heading">Upcoming</h5>
</a>
{items}
</div>
);
}
});
ScheduleEntryListItem = React.createClass({
openModal: function() {
$("#scheduleentry-modal").modal("show");
},
render: function() {
deadline = moment(this.props.item.deadline).format("MMM Do YYYY, h:mm A");
return (
<a className="list-group-item" href="#" onClick={this.openModal}>
<h5 className="list-group-item-heading">
{this.props.item.title}
</h5>
<small className="list-group-item-text">
{deadline}
</small>
</a>
);
}
});
Modal = React.createClass({
componentDidMount: function() {
$(this.getDOMNode())
.modal({backdrop: "static", keyboard: true, show: false});
},
componentWillUnmount: function() {
$(this.getDOMNode())
.off("hidden", this.handleHidden);
},
open: function() {
$(this.getDOMNode()).modal("show");
},
close: function() {
$(this.getDOMNode()).modal("hide");
},
render: function() {
return (
<div id="scheduleentry-modal" className="modal fade" tabIndex="-1">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">
<span>×</span>
</button>
<h4 className="modal-title">{this.props.title}</h4>
</div>
<div className="modal-body">
{this.props.children}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-danger pull-left" data-dismiss="modal">Delete</button>
<button type="button" className="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
)
}
});
ScheduleEntryModal = React.createClass({
render: function() {
var modal = null;
modal = (
<Modal title="Add Schedule Entry">
<form className="form-horizontal">
<div className="form-group">
<label htmlFor="title" className="col-sm-2 control-label">Title</label>
<div className="col-sm-10">
<input id="title" className="form-control" type="text" placeholder="Title" ref="title" name="title"/>
</div>
</div>
<div className="form-group">
<label htmlFor="deadline" className="col-sm-2 control-label">Deadline</label>
<div className="col-sm-10">
<input id="deadline" className="form-control" type="datetime-local" ref="deadline" name="deadline"/>
</div>
</div>
<div className="form-group">
<label htmlFor="completed" className="col-sm-2 control-label">Completed</label>
<div className="col-sm-10">
<input id="completed" className="form-control" type="checkbox" placeholder="completed" ref="completed" name="completed"/>
</div>
</div>
<div className="form-group">
<label htmlFor="description" className="col-sm-2 control-label">Description</label>
<div className="col-sm-10">
<textarea id="description" className="form-control" placeholder="Description" ref="description" name="description"/>
</div>
</div>
</form>
</Modal>
);
return (
<div className="scheduleentry-modal">
{modal}
</div>
);
}
});
Other comments and improvements to the code are appreciated.

I was recently looking for a nice solution to this without adding React-Bootstrap to my project (as Bootstrap 4 is about to be released).
This is my solution: https://jsfiddle.net/16j1se1q/1/
let Modal = React.createClass({
componentDidMount(){
$(this.getDOMNode()).modal('show');
$(this.getDOMNode()).on('hidden.bs.modal', this.props.handleHideModal);
},
render(){
return (
<div className="modal fade">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Modal title</h4>
</div>
<div className="modal-body">
<p>One fine body…</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
)
},
propTypes:{
handleHideModal: React.PropTypes.func.isRequired
}
});
let App = React.createClass({
getInitialState(){
return {view: {showModal: false}}
},
handleHideModal(){
this.setState({view: {showModal: false}})
},
handleShowModal(){
this.setState({view: {showModal: true}})
},
render(){
return(
<div className="row">
<button className="btn btn-default btn-block" onClick={this.handleShowModal}>Open Modal</button>
{this.state.view.showModal ? <Modal handleHideModal={this.handleHideModal}/> : null}
</div>
);
}
});
React.render(
<App />,
document.getElementById('container')
);
The main idea is to only render the Modal component into the React DOM when it is to be shown (in the App components render function). I keep some 'view' state that indicates whether the Modal is currently shown or not.
The 'componentDidMount' and 'componentWillUnmount' callbacks either hide or show the modal (once it is rendered into the React DOM) via Bootstrap javascript functions.
I think this solution nicely follows the React ethos but suggestions are welcome!

You can use React-Bootstrap (https://react-bootstrap.github.io/components/modal). There is an example for modals at that link. Once you have loaded react-bootstrap, the modal component can be used as a react component:
var Modal = ReactBootstrap.Modal;
can then be used as a react component as
<Modal/>.
For Bootstrap 4, there is react-strap (https://reactstrap.github.io). React-Bootstrap only supports Bootstrap 3.

getDOMNode() is deprecated. Instead use ref to access DOM element. Here is working Modal component (Bootstrap 4).
Decide whether to show or not to show Modal component in parent component.
Example: https://jsfiddle.net/sqfhkdcy/
class Modal extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
$(this.modal).modal('show');
$(this.modal).on('hidden.bs.modal', handleModalCloseClick);
}
render() {
return (
<div>
<div className="modal fade" ref={modal=> this.modal = modal} id="exampleModal" tabIndex="-1" role="dialog" aria- labelledby="exampleModalLabel" aria-hidden="true">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title" id="exampleModalLabel">Modal title
</h5>
<button type="button" className="close" data- dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
...
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data- dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
Edit:
Here are the necessary imports to make it work:
import $ from 'jquery';
window.jQuery = $;
window.$ = $;
global.jQuery = $;

I've only used bootstrap cdn (css + js) to achieve "reactstrap" like solution. I've used props.children to pass dynamic data from parent to child components. You can find more about this here. In this way you have three separate components modal header, modal body and modal footer and they are totally independent from each other.
//Modal component
import React, { Component } from 'react';
export const ModalHeader = props => {
return <div className="modal-header">{props.children}</div>;
};
export const ModalBody = props => {
return <div className="modal-body">{props.children}</div>;
};
export const ModalFooter = props => {
return <div className="modal-footer">{props.children}</div>;
};
class Modal extends Component {
constructor(props) {
super(props);
this.state = {
modalShow: '',
display: 'none'
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
}
openModal() {
this.setState({
modalShow: 'show',
display: 'block'
});
}
closeModal() {
this.setState({
modalShow: '',
display: 'none'
});
}
componentDidMount() {
this.props.isOpen ? this.openModal() : this.closeModal();
}
componentDidUpdate(prevProps) {
if (prevProps.isOpen !== this.props.isOpen) {
this.props.isOpen ? this.openModal() : this.closeModal();
}
}
render() {
return (
<div
className={'modal fade ' + this.state.modalShow}
tabIndex="-1"
role="dialog"
aria-hidden="true"
style={{ display: this.state.display }}
>
<div className="modal-dialog" role="document">
<div className="modal-content">{this.props.children}</div>
</div>
</div>
);
}
}
export default Modal;
//App component
import React, { Component } from 'react';
import Modal, { ModalHeader, ModalBody, ModalFooter } from './components/Modal';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
modal: false
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({ modal: !this.state.modal });
}
render() {
return (
<div className="App">
<h1>Bootstrap Components</h1>
<button
type="button"
className="btn btn-secondary"
onClick={this.toggle}
>
Modal
</button>
<Modal isOpen={this.state.modal}>
<ModalHeader>
<h3>This is modal header</h3>
<button
type="button"
className="close"
aria-label="Close"
onClick={this.toggle}
>
<span aria-hidden="true">×</span>
</button>
</ModalHeader>
<ModalBody>
<p>This is modal body</p>
</ModalBody>
<ModalFooter>
<button
type="button"
className="btn btn-secondary"
onClick={this.toggle}
>
Close
</button>
<button
type="button"
className="btn btn-primary"
onClick={this.toggle}
>
Save changes
</button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default App;

I Created this function:
onAddListItem: function () {
var Modal = ReactBootstrap.Modal;
React.render((
<Modal title='Modal title' onRequestHide={this.hideListItem}>
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
</Modal>
), document.querySelector('#modal-wrapper'));
}
And then used it on my Button trigger.
To 'hide' the Modal:
hideListItem: function () {
React.unmountComponentAtNode(document.querySelector('#modal-wrapper'));
},

You can use the model from the react-bootstrap from link and it's basically a function based
function Example() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow}>
Launch demo modal
</Button>
<Modal show={show} onHide={handleClose} animation={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={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
and You can convert it into the class component
import React, { Component } from "react";
import { Button, Modal } from "react-bootstrap";
export default class exampleextends Component {
constructor(props) {
super(props);
this.state = {
show: false,
close: false,
};
}
render() {
return (
<div>
<Button
variant="none"
onClick={() => this.setState({ show: true })}
>
Choose Profile
</Button>
<Modal
show={this.state.show}
animation={true}
size="md" className="" shadow-lg border">
<Modal.Header className="bg-danger text-white text-center py-1">
<Modal.Title className="text-center">
<h5>Delete</h5>
</Modal.Title>
</Modal.Header>
<Modal.Body className="py-0 border">
body
</Modal.Body>
<Modal.Footer className="py-1 d-flex justify-content-center">
<div>
<Button
variant="outline-dark" onClick={() => this.setState({ show: false })}>Cancel</Button>
</div>
<div>
<Button variant="outline-danger" className="mx-2 px-3">Delete</Button>
</div>
</Modal.Footer>
</Modal>
</div>
);
}
}

You can try this modal:https://github.com/xue2han/react-dynamic-modal
It is stateless and can be rendered only when needed.So it is very easy to use.Just like this:
class MyModal extends Component{
render(){
const { text } = this.props;
return (
<Modal
onRequestClose={this.props.onRequestClose}
openTimeoutMS={150}
closeTimeoutMS={150}
style={customStyle}>
<h1>What you input : {text}</h1>
<button onClick={ModalManager.close}>Close Modal</button>
</Modal>
);
}
}
class App extends Component{
openModal(){
const text = this.refs.input.value;
ModalManager.open(<MyModal text={text} onRequestClose={() => true}/>);
}
render(){
return (
<div>
<div><input type="text" placeholder="input something" ref="input" /></div>
<div><button type="button" onClick={this.openModal.bind(this)}>Open Modal </button> </div>
</div>
);
}
}
ReactDOM.render(<App />,document.getElementById('main'));

Thanks to #tgrrr for a simple solution, especially when 3rd party library is not wanted (such as React-Bootstrap). However, this solution has a problem: modal container is embedded inside react component, which leads to modal-under-background issue when outside react component (or its parent element) has position style as fixed/relative/absolute. I met this problem and came up to a new solution:
"use strict";
var React = require('react');
var ReactDOM = require('react-dom');
var SampleModal = React.createClass({
render: function() {
return (
<div className="modal fade" tabindex="-1" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Title</h4>
</div>
<div className="modal-body">
<p>Modal content</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" className="btn btn-primary">OK</button>
</div>
</div>
</div>
</div>
);
}
});
var sampleModalId = 'sample-modal-container';
var SampleApp = React.createClass({
handleShowSampleModal: function() {
var modal = React.cloneElement(<SampleModal></SampleModal>);
var modalContainer = document.createElement('div');
modalContainer.id = sampleModalId;
document.body.appendChild(modalContainer);
ReactDOM.render(modal, modalContainer, function() {
var modalObj = $('#'+sampleModalId+'>.modal');
modalObj.modal('show');
modalObj.on('hidden.bs.modal', this.handleHideSampleModal);
}.bind(this));
},
handleHideSampleModal: function() {
$('#'+sampleModalId).remove();
},
render: function(){
return (
<div>
<a href="javascript:;" onClick={this.handleShowSampleModal}>show modal</a>
</div>
)
}
});
module.exports = SampleApp;
The main idea is:
Clone the modal element (ReactElement object).
Create a div element and insert it into document body.
Render the cloned modal element in the newly inserted div element.
When the render is finished, show modal. Also, attach an event listener, so that when modal is hidden, the newly inserted div element will be removed.

Reactstrap also has an implementation of Bootstrap Modals in React. This library targets Bootstrap version 4, whereas react-bootstrap targets version 3.X.

I got the following code working with bootstrap 5 and react hooks
const ref = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
if (ref.current) {
ref.myModal = new bootstrap.Modal(ref.current, { backdrop: true });
}
}, [ref]);
to show the modal i use this code inside my component
<button
className="btn btn-primary"
onClick={() => {
if (ref.myModal) {
ref.myModal.show();
}
}}
>
open modal
</button>
<div
className="modal fade"
tabIndex={-1}
aria-labelledby="uploadYoutubeModalLabel"
aria-hidden="true"
ref={ref}
>
<div className="modal-dialog">bla</div>
</div>
this binds myModel to the ref and you can call ref.myModal.show() to open the modal and ref.myModal.hide()

The quickest fix would be to explicitly use the jQuery $ from the global context (which has been extended with your $.modal() because you referenced that in your script tag when you did ):
window.$('#scheduleentry-modal').modal('show') // to show
window.$('#scheduleentry-modal').modal('hide') // to hide
so this is how you can about it on react
import React, { Component } from 'react';
export default Modal extends Component {
componentDidMount() {
window.$('#Modal').modal('show');
}
handleClose() {
window.$('#Modal').modal('hide');
}
render() {
<
div className = 'modal fade'
id = 'ModalCenter'
tabIndex = '-1'
role = 'dialog'
aria - labelledby = 'ModalCenterTitle'
data - backdrop = 'static'
aria - hidden = 'true' >
<
div className = 'modal-dialog modal-dialog-centered'
role = 'document' >
<
div className = 'modal-content' >
// ...your modal body
<
button
type = 'button'
className = 'btn btn-secondary'
onClick = {
this.handleClose
} >
Close <
/button> < /
div > <
/div> < /
div >
}
}

Just add href='#scheduleentry-modal' to the element you want to open the modal with
Or using jQuery: $('#scheduleentry-modal').modal('show');

Related

How to trigger bootstrap modal programatically in reactjs

Onclick of a button i need to validate some data, if it is true then i need to open modal or no. But in my condition modal is opening for every click unable to it programatically
function verifyOtp(){
if(sucsess){}
else{}
}
<button onClick={()}=>verifyOtp() data-toggle="modal" data-target="#successModal">
</button>
<div className="modal fade" id="successModal" tabindex="-1" role="dialog" aria-labelledby = "emailModalLabel" aria-hidden="true">
<div className="modal-dialog email-modal-dialog" role="document">
<div className="modal-content verify-modal-dialog">
<div className="modal-header email-modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<p className="modal-title email-modal-title" id="emailModalLabel">Succesfull</p>
</div>
</div>
</div>
You Need to use State here is the working-class component example of a model. if you are using functional components then use useState() hook instead of this.setState() method
import React from "react";
export default class AddNewList extends React.Component {
state = {
showModal: false
};
closeModal = () => {
this.setState({ showModal: false });
};
onSave = () => {
console.log("i saved the data.");
this.setState({ showModal: false });
};
verifyOtp = () => {
//your success value
if (true) {
this.setState({ showModal: true });
}
};
render() {
return (
<>
<div>
<button onClick={this.verifyOtp} className="btn btn-primary btn-lg">
Open Modal
</button>
</div>
{this.state.showModal && (
<div className="" id="addnewlist">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title"> Model Header</h4>
</div>
<div className="modal-body">
test
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-danger"
data-dismiss="modal"
onClick={this.closeModal}
>
Close
</button>
<button
type="button"
className="btn btn-outline-success"
onClick={this.onSave}
>
Save
</button>
</div>
</div>
</div>
</div>
)}
</>
);
}
}
Skeleton for the functional component
import React, {useState} from 'react'
const [showModel,setShowModel] = useState(false);
function AddNewList (){
closeModal = () => {
setShowModel(false);
};
onSave = () => {
setShowModel(false);
};
verifyOtp = () => {
//your success value
if (true) {
setShowModel(true);
}
};
return render();
}

Open a modal popUp in React

I have this button in react:
<button type="button" className="btn btn-primary" onClick={()=>openPopUp(object)}>
Manage Permissions
</button>
and when I click the buton I want to open this popUp:
PopUp.js:
const PopUp = (props) => {
return (
<div className="modal fade" tabIndex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{props.object.name}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{props.object.permissions.map((permission) => {
return (
<li key={permission.code}>
{permission.name}
{props.showDeleteButton(permission.id, props.object.name)}
<p> </p>
</li>
)
})}
<form onSubmit={e => props.addPermission(e, props.object)}>
<label>
Insert a permission:
<input type="text" value={props.object.value} onChange={props.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
</div>
</div>
</div>
)
}
To do that, I did this, but the pop up wont open:
let openPopUp=(object)=>{
return <PopUp object={object} cont={cont} onChange={handleChange} addPermission={addPermission} showDeleteButton={showDeleteButton}/>
}
There is any error thrown, the popUp just doesn´t open.
It is because openPopUp is a onclick handler, it will not return anything to render. To achieve your goal, simply use a state variable with initial value as false, and update that value in openPopUp method. Use that bool for conditional rendering of PopUp component.
Like this:
constructor() {
super();
this.state = {
openPopUp: false,
object: null
}
}
openPopUp(object) {
this.setState({
openPopUp: true,
object: object
})
}
render() {
return (
<div>
....
{this.state.openPopUp &&
<PopUp object={this.state.object} cont={cont} onChange={handleChange} addPermission={addPermission} showDeleteButton={showDeleteButton} />}
....
</div>
)
}

My bootstrap modal won't close upon clicking the 'x' or Close

For some reason, my bootstrap modal won't close. I can preview the image in the modal just fine but when I try to close it, it doesn't work.
I tried to put <div id="myModal" class="modal fade" role="dialog"></div> on top of the existing <div className="modal-dialog"></div> but if I do that, then the modal won't even appear upon clicking Preview Image image button.
What am I doing wrong & how can I fix it?
Here's my code:
import React, { Component } from 'react';
class Upload extends Component {
constructor(props) {
super(props);
this.state = {
selectedFile: null,
prevImgURL: '',
imgPrev: false
};
this.imageChange = this.imageChange.bind(this);
}
imagePreview = (newPostImageBool) => {
this.setState({imgPrev: newPostImageBool});
};
imageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
selectedFile: file,
prevImgURL: reader.result
});
}
if(file) reader.readAsDataURL(file);
}
render() {
return (
<div>
<input
id="new_post_image"
type="file"
onChange={this.imageChange}
name="image"
accept="image/*"
/>
<button
type="button"
onClick={() => this.imagePreview(true)}
className="btn btn-info btn-lg"
data-toggle="modal"
data-target="#myModal"
>
Preview Image
</button>
{this.state.imgPrev ?
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">×</button>
<h4 className="modal-title">Preview</h4>
</div>
<div className="modal-body">
<img id="pic" className="img-responsive" src={this.state.prevImgURL}/>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
: null}
</div>
);
}
}
export default Upload;
import React, { Component } from 'react';
class Upload extends Component {
constructor(props) {
super(props);
this.state = {
selectedFile: null,
prevImgURL: '',
imgPrev: false
};
this.imageChange = this.imageChange.bind(this);
}
imagePreview = (newPostImageBool) => {
this.setState({imgPrev: newPostImageBool});
};
closeModal = () => {
this.setState({imgPrev : false});
};
imageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
selectedFile: file,
prevImgURL: reader.result
});
}
if(file) reader.readAsDataURL(file);
}
render() {
return (
<div>
<input
id="new_post_image"
type="file"
onChange={this.imageChange}
name="image"
accept="image/*"
/>
<button
type="button"
onClick={() => this.imagePreview(true)}
className="btn btn-info btn-lg"
data-toggle="modal"
data-target="#myModal"
>
Preview Image
</button>
{!!this.state.imgPrev &&
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" onClick={this.closeModal}>×</button>
<h4 className="modal-title">Preview</h4>
</div>
<div className="modal-body">
<img id="pic" className="img-responsive" src={this.state.prevImgURL}/>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal" onClick={this.closeModal}>Close</button>
</div>
</div>
</div>
}
</div>
);
}
}
export default Upload;

ReactJS looping executeAction

I have two react modals defined with onAfterOpens like so:
import React from 'react';
import JobList from './JobList';
import RightPanel from './RightPanel';
import LoadJobsScreen from '../../actions/jobs-screen/LoadJobsScreen';
import UserStore from '../../stores/UserStore';
import LoadUsers from '../../actions/global/LoadUsers';
import LoadUsersByDepartment from '../../actions/global/LoadUsersByDepartment';
import Modal from 'react-modal';
export default class JobScreen extends React.Component {
static contextTypes = {
executeAction: React.PropTypes.func.isRequired,
getStore: React.PropTypes.func.isRequired
};
componentWillMount() {
this.displayName = 'JobScreen'
this.state = {
traderModalOpened: false,
OFTModalOpened: false,
users: this.context.getStore(UserStore).getUsers(),
}
this.context.getStore(UserStore).on('change', () => {
this.setState({
users: this.context.getStore(UserStore).getUsers()
});
});
this.context.executeAction(LoadJobsScreen, this);
}
toggleTraderModal() {
this.setState({
traderModalOpened: !this.state.traderModalOpened
});
console.log(this.state.traderModalOpened);
}
toggleOFTModal() {
this.setState({
OFTModalOpened: !this.state.OFTModalOpened
});
console.log(this.state.OFTModalOpened);
}
render() {
var users = [];
this.state.users.forEach((user) => {
users.push(
<option value={user.id}>{user.firstName}</option>
);
});
return (
<div className="jobs-screen">
<div className="col-xs-12 col-sm-10 job-list" ><JobList toggleTraderModal={this.toggleTraderModal.bind(this)} toggleOFTModal={this.toggleOFTModal.bind(this)}/></div>
<div className="col-xs-12 col-sm-2 panel-container">
<div className="right-panel pull-right"><RightPanel /></div>
</div>
<Modal
isOpen={this.state.traderModalOpened}
className="modal-dialog"
overlayClassName="modal show"
onAfterOpen={this.context.executeAction(LoadUsersByDepartment, 5)}
>
<div className="modal-content">
<div className="modal-header">
<button type="button" onClick={this.toggleTraderModal.bind(this)} className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Set trader</h4>
</div>
<div className="modal-body">
<select>
{users}
</select>
</div>
<div className="modal-footer">
<button type="button" onClick={this.toggleTraderModal.bind(this)} className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</Modal>
<Modal
isOpen={this.state.OFTModalOpened}
className="modal-dialog"
overlayClassName="modal show"
onAfterOpen={this.context.executeAction(LoadUsersByDepartment, 8)}
>
<div className="modal-content">
<div className="modal-header">
<button type="button" onClick={this.toggleOFTModal.bind(this)} className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Set OFT member</h4>
</div>
<div className="modal-body">
</div>
<div className="modal-footer">
<button type="button" onClick={this.toggleOFTModal.bind(this)} className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</Modal>
</div>
);
}
}
My action:
import qwest from 'qwest';
export default function LoadUsersByDepartment(actionContext, payload) {
return qwest.get('/users/fetch/department', {department_id: payload}, {responseType: 'json'})
.then(function (response) {
actionContext.dispatch('RECEIVED_USERS_DATA', {data: response.response})
})
};
But in my console I am seeing that the actions are being called constantly. What is happening and how do I get it to just perform the action when the modal is opened?
Just a quick shot here. Try this one, instead of existing statement
<Modal
...
onAfterOpen={() => this.context.executeAction(LoadUsersByDepartment, 8)}
...
>
What your code does is:
when modal is opened, execute the result from this.context.executeAction(LoadUsersByDepartment, 8) call.
Adjusted code executes your action (not it's result) when modal is opened.

ReactJS Modal as component

How do I create a modal using Reactjs? I am just using the CSS from Bootstrap's modal (none of the JS).
I have created a modal component:
import React from 'react';
class Modal extends React.Component {
constructor() {
super();
}
componentWillMount() {
this.setState({
open: false
})
}
onClick() {
this.setState({
open: !this.state.open
})
}
render() {
return (
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">{this.props.title}</h4>
</div>
<div class="modal-body">
{this.props.children}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
)
}
}
export default Modal;
I want to call it from in here somehow:
import React from 'react';
import UrgencyToggle from './UrgencyToggle';
import ApproveButton from './ApproveButton';
import ShippingTable from './ShippingTable';
import DropdownButtonList from '../global/DropdownButtonList';
import Modal from '../global/Modal';
export default class Job extends React.Component {
setUrgency(urgency) {
actionContext.dispatch('SET_JOB_URGENCY', { data: urgency})
};
changeTrader(e) {
}
changeOft() {
}
render() {
return (
<div className="row users">
<div className="col-xs-12 col-sm-4">
<span className="title">Trader</span>
<span className="name">{this.props.job.user_name}<img
src="/images/system-icons/pencil.png" width="13"
onClick={this.changeTrader}
title="Change which trader owns this job."/></span>
</div>
<div className="col-xs-12 col-sm-4">
<span className="title">CEX</span>
<span
className="name">{this.props.job.cex_user_name ? this.props.job.cex_user_name : 'None assigned'}</span>
</div>
<div className="col-xs-12 col-sm-4">
<span className="title">OFT</span>
<span
className="name">{this.props.job.oft_user_name ? this.props.job.oft_user_name : 'None assigned'}<img
title="Set the OFT user for this job." src="/images/system-icons/pencil.png"
onClick={this.changeOft}
width="13"/></span>
</div>
</div>
)
}
};
Modal:
import React from 'react';
class Modal extends React.Component {
constructor() {
super();
}
render() {
let open = this.props.open;
return (
<div className={'modal fade'+(open ? '' : 'hide')} tabindex="-1" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">{this.props.title}</h4>
</div>
<div className="modal-body">
{this.props.children}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
)
}
}
export default Modal;
Job:
import React from 'react';
import UrgencyToggle from './UrgencyToggle';
import ApproveButton from './ApproveButton';
import ShippingTable from './ShippingTable';
import DropdownButtonList from '../global/DropdownButtonList';
import Modal from '../global/Modal';
export default class Job extends React.Component {
constructor(props) {
super(props);
this.toggleModal = this.toggleModal.bind(this);
this.state = {open: false}
}
setUrgency(urgency) {
actionContext.dispatch('SET_JOB_URGENCY', { data: urgency})
};
toggleModal() {
this.setState({
open: this.state.modal
});
}
render() {
return (
<div className="row users">
<div className="col-xs-12 col-sm-4">
<span className="title">Trader</span>
<span className="name">{this.props.job.user_name}<img
src="/images/system-icons/pencil.png" width="13"
onClick={this.toggleModal}
title="Change which trader owns this job."/></span>
</div>
<div className="col-xs-12 col-sm-4">
<span className="title">CEX</span>
<span
className="name">{this.props.job.cex_user_name ? this.props.job.cex_user_name : 'None assigned'}</span>
</div>
<div className="col-xs-12 col-sm-4">
<span className="title">OFT</span>
<span
className="name">{this.props.job.oft_user_name ? this.props.job.oft_user_name : 'None assigned'}<img
title="Set the OFT user for this job." src="/images/system-icons/pencil.png"
onClick={this.toggleModal}
width="13"/></span>
</div>
</div>
)
}
};
Control your Modal's state from the parent component Job. The calling function which activates/deactivates the Modal should also lie inside the parent Job component.
export class Modal extends React.Component {
// this.props.open holds the value whether the modal is open or not
// this.props.toggleModal holds the function for opening/closing modal
render() {
let open = this.props.open;
// return JSX
}
}
Inside your job component, pass this.state.open and this.toggleModal function as props to Modal Component.
export default class Job extends React.Component {
constructor(props) {
super(props);
this.toggleModal = this.toggleModal.bind(this);
this.state = {
open: false,
}
}
toggleModal() {
this.setState({
open: this.state.modal,
});
}
render() {
return (
<div>
{/* your JSX */}
<Modal open={this.state.open} toggleModal={this.toggleModal} />
</div>
)
}
}
You can also use this to declare your default props, since you are using one
static propTypes = {
open: PropTypes.bool,
};
static defaultProps = {
open: false //default
};

Categories