how to hide a bootstrap modal using React JSX - reactjs

I am learning react and I want to close a bootstrap modal after a 'Post' callback
So, in the below code I want to hide the modal in the 'hideModal' method when onClick={() => postDocument.callApi(this.state.document, this.hideModal)} calls back.
How can I do this?
import React, { Component } from "react";
import postDocument from "./../rest/PostDocument";
import fetchPersons from "./../rest/FetchPersons";
import PersonList from "./../components/PersonList";
import ShowDatePicker from "./../components/ShowDatePicker";
import moment from "moment";
class SaveDocument extends Component {
state = {
persons: [],
document: {
documentDate: moment(),
personFrom: {
id: ""
},
personTo: {
id: ""
},
comments: ""
}
};
hideModal = hideModalInfo => {
// How do I hide the modal here!
};
render() {
return (
<div
className="modal fade"
id="basicExampleModal"
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">
Save document
</h5>
<button
type="button"
className="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-primary"
onClick={() => postDocument.callApi(this.state.document, this.hideModal)}
>
Save changes
</button>
</div>
</div>
</div>
</div>
);
}
}
export default SaveDocument;

You can import jquery and call Bootstrap's modal("hide") method...
import $ from "jquery";
...
hideModal = hideModalInfo => {
$("#myModal").modal("hide");
};
https://codesandbox.io/s/ykkvl7547j

A different approach is to simulate a .click() on the close button,
...
const closeRef = useRef();
...
<button
type="button"
className="close"
data-dismiss="modal"
aria-label="Close"
ref={useRef}
>
...
<button
type="button"
className="btn btn-primary"
onClick={() => {closeRef.current.click()}}
>
Save changes
</button>

you should bind that method. onClick={this.handleClick}
class SaveDocument extends Component {
constructor(props){
super(props);
state = { ... }
//This binding is necessary to make `this` work in the callback
this.hideModal = this.hideModal.bind(this);
}
render(){
return (<button
type="button"
onClick={this.hideModal)}
>)
}
};
more info about bindings
Also, i have a basic example working:
https://codepen.io/ene_salinas/pen/yRGMpG
ReactModal.setAppElement('#main');
class ExampleApp extends React.Component {
constructor () {
super();
this.state = {
showModal: false
};
this.handleOpenModal = this.handleOpenModal.bind(this);
this.handleCloseModal = this.handleCloseModal.bind(this);
}
handleOpenModal () {
this.setState({ showModal: true });
}
handleCloseModal () {
this.setState({ showModal: false });
}
render () {
return (
<div>
<button onClick={this.handleOpenModal}>Trigger Modal</button>
<ReactModal
isOpen={this.state.showModal}
contentLabel="onRequestClose Example"
onRequestClose={this.handleCloseModal}
className="Modal"
overlayClassName="Overlay"
>
<p>Modal text!</p>
<button onClick={this.handleCloseModal}>Close Modal</button>
</ReactModal>
</div>
);
}
}
const props = {};
ReactDOM.render(<ExampleApp {...props} />, document.getElementById('main'))
In your code (if you have jquery):
constructor(){
this.state = { hideModal = true }
}
hideModal() {
this.state.hideModal = true
//i dont recommend, i prefer use the state
$("#modal").hide()
};
showModal() {
this.state.hideModal = false
//i dont recommend, i prefer use the state
$("#modal").show()
};
render(){
<button value="open modal" onClick={showModal} />
//div modal
<div class={this.state.hideModal ? 'hide' : 'show'}>
<button value="close modal" onClick={hideModal} />
</div>
}

bootstarp has jquery based functions so
1.if you use jquery here use this one
$("#basicExampleModal").modal("hide");
2.Or we can use data-dismiss="modal" to that button
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>

Related

React Element appearing after second button click

Im fairly new to react and im trying to build a webapp. I'm having this problem when it comes to displaying a div that contains multiple input fields, the field lesson dont show until the second time I click my create button. However it's working perfectly when I render it with this code:
Note: Im rendering TestClonereact in CourseVideoStructure
This is CourseVideoStructure.js
import React, { Component } from 'react'
import Sidenavbar from '../../Components/Sidenavbar'
import '../../Style/pagestyle/CourseVideoStructure.css'
import Footer from '../../Components/Footer'
import { Avatar } from '#material-ui/core'
import 'react-dropzone-uploader/dist/styles.css'
import EdiText from 'react-editext'
import TestClonereact from '../../Components/TestClonereact'
export default class CourseVideoStructure extends Component {
onSave = val => {
console.log('Edited Value -> ', val)
}
id = 1;
state = {
listq: [],
}
lessons(id) {
return (
<div key={id} id={`sectionlesson-${id}`}>
<div className="section-titles">
<i class="material-icons" id="iconsectionlist" type="button" >list</i>
<EdiText
type='text'
value='Lesson Title'
onSave={this.onSave}
/>
<i class="material-icons" id="iconsectiondel" type="button">smart_display</i>
<i class="material-icons" id="iconsectiondel" onClick={e => this.remove(`${id}`)} type="button" >delete</i>
</div>
<div className="testh" >
</div>
</div>
)
}
addlesson1 = () => {
const listlesson = this.state.listq;
listlesson.push(this.lessons(this.id))
this.setState({ listlesson });
this.id++;
}
remove(id) {
const newList = this.state.listq.filter(lessons => lessons.key !== id);
this.setState({
listq: newList
})
}
addsection = () => {
const list = this.state.list;
list.push(this.section(this.id))
this.setState({ list });
this.id++;
}
render() {
return (
<div>
<Sidenavbar></Sidenavbar>
<nav class="navbar navbar-expand-md navbar-white">
<a class="navbar-brand" href="#"></a>
<Avatar className="avatar" aria-controls="simple-menu" aria-haspopup="true" src="https://avatars2.githubusercontent.com/u/56764954?s=400&u=57d85794b8c753245870e2f9051b303d1188b01d&v=4" ></Avatar>
</nav>
<div className="row">
<div className="fluid-xld" id="coursevideo-structure-xld">
<div className="course-structure-form-dsp col-md-12">
<h3 className="container"> Video Course Structure</h3><br></br><br></br>
<div className="course-structure-form " id="csf1">
<div className="section-heading">
<i class="material-icons" id="iconsection">api</i>
<EdiText
type='text'
value='Section Title'
onSave={this.onSave}
/>
</div>
{
this.state.listq.map(lessons => lessons)
}
<div className="addnewlesson" onClick={e => this.addlesson1()}>
<i class="material-icons" id="iconsectionde" role="button" type="button" >add_circle</i><span>Add New Lesson</span>
</div>
</div>
</div>
<div>
<TestClonereact></TestClonereact>
</div>
</div>
</div>
<Footer></Footer>
</div>
)
}
}
However when I try to render this component in CourseVideoStructure(the code above) it doesnt render as I would like it to:
This is TestClonereact.jsx:
import React, {useEffect, useReducer} from 'react'
import '../Style/pagestyle/CourseVideoStructure.css'
import EdiText from 'react-editext'
class TestClonereact extends React.Component {
constructor(props) {
super(props);
this.state = {
listq: [],
list: []
};
}
onSave = val => {
console.log('Edited Value -> ', val)
}
id = 1;
lessons(id){
return (
<div key={id} id={`sectionlesson-${id}`}>
<div className="section-titles">
<i class="material-icons" id="iconsectionlist" type="button" >list</i>
<EdiText
type='text'
value='Lesson Title'
onSave={this.onSave}
/>
<i class="material-icons" id="iconsectiondel" type="button">smart_display</i>
<i class="material-icons" id="iconsectiondel" onClick={e => this.remove(`${id}`)} type="button" >delete</i>
</div>
<div className="testh" >
</div>
</div>
)
}
section(id){
return (
<div key={id} id={`sds-${id}`}>
<div className="course-structure-form " id="csf1">
<div className="section-heading">
<i class="material-icons" id="iconsection">api</i>
<EdiText
type='text'
value='Section Title'
onSave={this.onSave}
/>
</div>
{
this.state.listq.map(lessons => lessons)
}
<div className="addnewlesson" onClick={async () => { this.addlesson();}}>
<i class="material-icons" id="iconsectionde" role="button" type="button" >add_circle</i><span>Add New Lesson</span>
</div>
</div>
</div>
)
}
addsection = () => {
const list = this.state.list;
list.push(this.section(this.id))
this.setState({ list });
this.id++;
}
addlesson = () => {
const listlesson = this.state.listq;
listlesson.push(this.lessons(this.id))
this.setState({ listlesson });
this.id++;
}
deletelesson = () => {
const list = this.state.list;
list.splice(this.section(this.id))
this.setState({ list });
this.id--;
}
remove(id) {
const newList = this.state.listq.filter(lessons => lessons.key !== id);
this.setState({
listq: newList
})
}
render(){
return (
<div>
{
this.state.list.map(section => section)
}
<div className="add-section-button-structure">
<button class="tablink" onClick={e => this.addsection()} >Add New Section</button>
<button class="tablink" onClick={e => this.deletelesson()} >Delete Section</button>
<button class="tablink" >Preview</button>
<button class="tablink" >Submit</button>
</div>
</div>)
}
}
export default TestClonereact
So the result in images is this:
Working fine and Added Lessons 1 by 1 in the same Section:
Working Fine and able to add lessons
Problem is when I click on Add Lesson in the Second section, nothing happens but when I click on Add section again, the lesson appear in the 3rd section not the second one:
Problem image here
I've kept tryint to solve this issue with no luck. Any kind of help is much appreciated.
Forgive me for any horrible coding.

React - Using a Callback function to pass data from Child to Parent

I am currently making a simple Dropdown menu in which I want to pass certain state values to its parent so that the parent will fetch data from the backend.
I have written a callback function in my parent function that I am passing as a prop to the child; however, I am not getting any output when I log the change on the console, hence I don't think I am using the callback properly.
This is my dropdown menu:
class Dropdown extends Component {
constructor(props) {
super(props);
this.state = {
headerTitle: this.props.title,
teams: this.props.teams,
};
this.handleClick = this.handleClick.bind(this)
}
handleClick(teamID) {
this.setState({
headerTitle: this.state.teams[teamID].name
})
}
render() {
return (
<div className="btn-group w-100 d-flex">
<button type="button" className="btn-success w-100 dropdown-toggle" data-toggle="dropdown" onChange={this.props.handleTeam}>
{this.state.headerTitle}
</button>
<ul className="dropdown-menu pre-scrollable w-100" role="menu">
{this.state.teams.map((team) => {
return (
<li>
<a href="#/game-pred" className="dropdown-item d-flex justify-content-center" onClick={() => this.handleClick(team.id)} >{team.name}</a>
</li>
);
})}
</ul>
</div>
);
}
}
And this is my parent:
class GamePrediction extends Component {
constructor(props){
super(props);
this.state = {
teams: [],
count: 0,
};
this.handleTitleChange = this.handleTitleChange.bind(this);
}
handleTitleChange(newTitle) {
if (this.state.count == 2){
this.setState({
teams: [newTitle,this.state.teams[1]]
})
}
else if (this.state.count == 1) {
this.setState({
teams: [this.state.teams[0],newTitle],
count: 2
})
}
else {
this.setState({
teams: teams.push(newTitle),
count: this.state.count + 1
})
}
console.log("Change!",this.state.teams,this.state.count)
}
render() {
return (
<div className="button-group w-100 d-flex" >
<Dropdown title="Team 1" teams={teams} handleTeam={this.handleTitleChange} ref="team1"/>
<Dropdown title="Team 2" teams={teams} ref="team2"/>
</div>
);
}
}
It should also be noted that there are two dropdown menus from which the user can select one team for each dropdown, if that helps.
A <button> has an onClick, not an onChange,
so you probably want to change this
<button type="button" className="btn-success w-100 dropdown-toggle" data-toggle="dropdown" onChange={this.props.handleTeam}>
to this
<button type="button" className="btn-success w-100 dropdown-toggle" data-toggle="dropdown" onClick={this.props.handleTeam}>
Also I see that your handleTitleChange(newTitle) accepts a newTitle param, you can pass that param like this
<button type="button" className="btn-success w-100 dropdown-toggle" data-toggle="dropdown" onClick={() => this.props.handleTeam('My new Title')}>

I am trying to pass a value from one component with a click function to another

My app.js creates a widget layout, within it I have an handleWidgetSelection function which should take an id when an item is clicked in my modal component. When I console log in the handleWidgetSelection function I notice that the state is not updated and it remains null as I originally set it as. I am fairly new to react so any help would be great.
This is my app.js
class App extends Component {
constructor(props) {
super(props);
this.state={
selectedWidgetId: null, //initially set as null because no widget is selected
widgetOptions:[{name:"Data Table", comp:<DataTable/>},{name:"List", comp:<CheckboxList/>}],
widgets:[ //array for layout
{id:1, content: <DataTable/>},
{id:2, content: <CheckboxList/>},
{id:3, content: ""},
{id:4, content: ""}
],
isModalOpen: false
}
}
handleWidgetSelection=(id) => {
this.setState({selectedWidgetId: id})
console.log(this.state.selectedWidgetId); //trying to fix so this value does not always print null
}
.....
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
//I am passing my values to the AddWidgetDialog component here
<AddWidgetDialog handleWidgetSelection={this.handleWidgetSelection} widgets={this.state.widgetOptions} isModalOpen={this.state.isModalOpen} onRequestClose={this.onRequestClose} />
<Grid container spacing={24}>
{
this.state.widgets.map((widget,index)=>{
return(
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}><Swappable id={widget.id} content={widget.content} delete={this.deleteEvent.bind(this,index)} add={this.addEvent.bind(this,index)}/></Paper>
</Grid>
)
})
}
</Grid>
</div>
);
}
This is my AddWidgetDialog component
import React, { PropTypes } from 'react';
import Modal from 'react-modal';
const AddWidgetDialog = ({ handleWidgetSelection, widgets, isModalOpen, onRequestClose}) => {
const widgetItems = widgets.map((widget) => {
return (
<div className="list-group">
<a href="#" onClick={() => handleWidgetSelection(widget.name)} className="list-group-item">
<h6 className="list-group-item-heading">{widget.name}</h6>
</a>
</div>
);
});
return (
<Modal
className="Modal__Bootstrap modal-dialog"
isOpen={isModalOpen}>
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" onClick={onRequestClose}>
<span aria-hidden="true">×</span>
<span className="sr-only">Close</span>
</button>
<h4 className="modal-title">Add a widget</h4>
</div>
<div className="modal-body">
<h5>Pick a widget to add</h5>
{widgetItems}
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" onClick={onRequestClose}>Close</button>
</div>
</div>
</Modal>
);
};
export default AddWidgetDialog;
setState maybe asynchronous. See the docs Why is setState giving me the wrong value?
handleWidgetSelection=(id) => {
this.setState({selectedWidgetId: id})
console.log(this.state.selectedWidgetId); //no guarantee state is updated or not.
}
You should use console.log() in the callback as second argument to the setState
handleWidgetSelection=(id) => {
this.setState({selectedWidgetId: id},() => {
console.log(this.state.selectedWidgetId); //state is updated now.
})
}

Reactjs use function from parent

I have 2 files. One is my app.js and the other one is productmodal.js
app.js gets a productlist from an api call. It views these productst in a list.
When a user clicks on the image productmodal.js is showed.
productmodal.js shows a popup with a bigger image, productname(title) and a button called "Product niet aanwezig" (product unavailable) if the user clicks on this link a mail is send to an other user.
When the button is click I also want to activate an other function (getUpdatedProduct). This function is gonna do a long polling call to a link to check when the product is updated to a new product and update this product in the app.
The problem is: I don't know how to call the function 'getUpdatedProduct' in productmodal.js
I get an error: Uncaught TypeError: Cannot read property 'getUpdatedProduct' of undefined
I tried some of these solutions https://reactjs.org/docs/faq-functions.html. Especially the arrow function in render, because its generating a new function every time when the modal is clicked (which I need).
But nothing seems to work. Has anyone some idea's?
App.js:
import React from 'react';
import image from '../images/sogyologo.svg';
import ProductModal from './ProductModal.js';
class App extends React.Component {
constructor(props) {
super(props);
this.toggleModal = this.toggleModal.bind(this);
this.state = {
isLoading: true,
orders: [],
dealtOrders: [],
productDetail: [],
open: false,
modal: []
}
}
toggleModal(event)
{
console.log(event);
let itemIndex = event.target.getAttribute("data-itemIndex");
console.log(itemIndex);
const productModal = this.state.orders[itemIndex];
console.log(productModal);
this.setState({
open: true,
modal: this.state.orders[itemIndex]
});
}
handleClose() {
this.setState({
open: !this.state.open
});
}
componentWillMount() {
localStorage.getItem('orders') && this.setState({
orders: JSON.parse(localStorage.getItem('orders')),
isLoading: false
})
}
componentDidMount() {
if (!localStorage.getItem('orders')){
this.fetchData();
} else {
console.log('Using data from localstorage');
}
}
fetchData() {
fetch('http://localhost:54408/api/orders/all/testing-9!8-7!6/10-04-2018')
.then(response => response.json())
.then(parsedJSON => parsedJSON.map(product => (
{
productname: `${product.ProductName}`,
image: `${product.Image}`,
quantity: `${product.Quantity}`,
isconfirmed: `${product.IsConfirmed}`,
orderid: `${product.OrderId}`
}
)))
.then(orders => this.setState({
orders,
isLoading: false
}))
.catch(error => console.log('parsing failed', error))
}
// componentWillUpdate(nextProps, nextState) {
// localStorage.setItem('orders', JSON.stringify(nextState.orders));
// localStorage.setItem('ordersDate', Date.now());
// }
render() {
this.handleDoneAction = event =>
{
let itemIndex = event.target.getAttribute("data-itemIndex");
let prevOrders = [...this.state.orders];
let dealtOrders = [...this.state.dealtOrders];
const itemToMoveAtLast = prevOrders.splice(itemIndex, 1);
const addToDealtOrders = dealtOrders.concat(itemToMoveAtLast);
this.setState({dealtOrders: addToDealtOrders});
this.setState({orders: prevOrders});
};
this.handleUndoAction = event =>
{
let itemIndex = event.target.getAttribute("data-itemIndex");
let orders = [...this.state.orders];
let dealtOrders = [...this.state.dealtOrders];
const undoDealtOrder = dealtOrders.splice(itemIndex, 1);
const addToOrders = orders.concat(undoDealtOrder);
this.setState({orders: addToOrders});
this.setState({dealtOrders: dealtOrders});
};
const {isLoading, orders, dealtOrders} = this.state;
return (
<div>
<header>
<img src={image}/>
<h1>Boodschappenlijstje <button className="btn btn-sm btn-danger">Reload</button></h1>
</header>
<div className={`content ${isLoading ? 'is-loading' : ''}`}>
<div className="panel">
{
!isLoading && orders.length > 0 ? orders.map((order, index) => {
const {productname, image, quantity, orderid} = order;
return<div className="product" key={orderid}>
<div className="plaatjediv" onClick={this.toggleModal.bind(this) }>
<img className="img-responsive" data-itemIndex={index} src={image} />
</div>
<div className="productInfo">
<p>{productname}</p>
<p>Aantal: {quantity}</p>
</div>
<div className="bdone">
<button className="btn btn-lg btn-default btndone" data-itemIndex={index} onClick={this.handleDoneAction}>Done</button>
</div>
</div>
}) : null
}
</div>
<h2>Mandje</h2>
<div className="panel">
{
!isLoading && dealtOrders.length > 0 ? dealtOrders.map((dorder, index) => {
const {productname, image, quantity} = dorder;
return<div className="productDone" key={index}>
<div className="plaatjediv">
<img className="img-responsive" src={image} />
</div>
<div className="productInfo">
<p>{productname}</p>
<p>Aantal: {quantity}</p>
</div>
<div className="bdone">
<button className="btn btn-lg btn-default btndone" data-itemIndex={index} onClick={this.handleUndoAction}>Undo</button>
</div>
</div>
}) : null
}
</div>
<ProductModal open={this.state.open} handleClose={this.handleClose.bind(this)}
title={this.state.modal.productname} plaatje={this.state.modal.image} orderid={this.state.modal.orderid}/>
<div className="loader">
<div className="icon"></div>
</div>
</div>
</div>
);
}
}
export default App;
productmodal.js
import React from 'react';
class ProductModal extends React.Component {
constructor() {
super();
this.getUpdatedProduct = this.getUpdatedProduct.bind(this);
}
handleClose() {
this.props.handleClose();
}
UserAction(event) {
let orderid = event.target.value;
fetch('http://localhost:54408/api/orders/change/testing-9!8-7!6/' + orderid + '/10-04-2018');
console.log("order id = " + event.target.value);
this.getUpdatedProduct();
}
getUpdatedProduct() {
console.log("fetching new product");
}
render() {
//const open = this.props.open;
const {title, plaatje, open, orderid} = this.props;
return (
<div className={'modal fade in '+(open?'show':'')} role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" onClick={this.handleClose.bind(this)} 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">
<img className="plaatjediv img-responsive" src={plaatje} />
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default"
onClick={this.handleClose.bind(this)}>Sluiten
</button>
<button type="button" onClick={this.UserAction.bind()} value={orderid} className="btn btn-primary">Product niet aanwezig</button>
</div>
</div>
</div>
</div>
)
}
}
export default ProductModal;

Reactjs component modal onclick div

I am trying to make a modal component which I can reuse, but I don't get what I am doing wrong here. The Modal is not appearing. Can anyone help me out?
Little explanation about my app.
This app is loading a JSON url and shows a list of products, which can be marked as done. If you click the div plaatjediv you should get a popup (the modal) with details info over the clicked product.
EDIT: Edited the code as suggested here. I can see the state change to true and false if I click the div, but the Modal is still not appearing.
my code
App.js
import React from 'react';
import ProductModal from './ProductModal.js';
class App extends React.Component {
constructor(props) {
super(props);
this.toggleModal = this.toggleModal.bind(this);
this.state = {
isLoading: true,
orders: [],
dealtOrders: [],
open: false
}
}
toggleModal() {
this.setState({
open: !this.state.open
});
}
componentWillMount() {
localStorage.getItem('orders') && this.setState({
orders: JSON.parse(localStorage.getItem('orders')),
isLoading: false
})
}
componentDidMount() {
if (!localStorage.getItem('orders')){
this.fetchData();
} else {
console.log('Using data from localstorage');
}
}
fetchData() {
fetch('http://localhost:54408/api/orders/all/26-03-2018')
.then(response => response.json())
.then(parsedJSON => parsedJSON.map(product => (
{
productname: `${product.ProductName}`,
image: `${product.Image}`,
quantity: `${product.Quantity}`,
isconfirmed: `${product.IsConfirmed}`,
orderid: `${product.OrderId}`
}
)))
.then(orders => this.setState({
orders,
isLoading: false
}))
.catch(error => console.log('parsing failed', error))
}
render() {
this.handleDoneAction = event =>
{
let itemIndex = event.target.getAttribute("data-itemIndex");
let prevOrders = [...this.state.orders];
let dealtOrders = [...this.state.dealtOrders];
const itemToMoveAtLast = prevOrders.splice(itemIndex, 1);
const addToDealtOrders = dealtOrders.concat(itemToMoveAtLast);
this.setState({dealtOrders: addToDealtOrders});
this.setState({orders: prevOrders});
};
this.handleUndoAction = event =>
{
let itemIndex = event.target.getAttribute("data-itemIndex");
let orders = [...this.state.orders];
let dealtOrders = [...this.state.dealtOrders];
const undoDealtOrder = dealtOrders.splice(itemIndex, 1);
const addToOrders = orders.concat(undoDealtOrder);
this.setState({orders: addToOrders});
this.setState({dealtOrders: dealtOrders});
};
const {isLoading, orders, dealtOrders,open} = this.state;
return (
<div>
<header>
<img src="/images/header.jpg"/>
<h1>Boodschappenlijstje <button className="btn btn-sm btn-danger">Reload</button></h1>
</header>
<ProductModal open={open} />
<div className={`content ${isLoading ? 'is-loading' : ''}`}>
<div className="panel">
{
!isLoading && orders.length > 0 ? orders.map((order, index) => {
const {productname, image, quantity, orderid} = order;
return<div className="product" key={orderid}>
<div className="plaatjediv" onClick={this.toggleModal}>
<img className="img-responsive" src={image} />
</div>
<div className="productInfo">
<p>{productname}</p>
<p>Aantal: {quantity}</p>
</div>
<div className="bdone">
<button className="btn btn-lg btn-default btndone" data-itemIndex={index} onClick={this.handleDoneAction}>Done</button>
</div>
</div>
}) : null
}
</div>
<h2>Mandje</h2>
<div className="panel">
{
!isLoading && dealtOrders.length > 0 ? dealtOrders.map((dorder, index) => {
const {productname, image, quantity, orderid} = dorder;
return<div className="productDone" key={index}>
<div className="plaatjediv">
<img className="img-responsive" src={image} />
</div>
<div className="productInfo">
<p>{productname}</p>
<p>Aantal: {quantity}</p>
</div>
<div className="bdone">
<button className="btn btn-lg btn-default btndone" data-itemIndex={index} onClick={this.handleUndoAction}>Undo</button>
</div>
</div>
}) : null
}
</div>
<div className="loader">
<div className="icon"></div>
</div>
</div>
</div>
);
}
} export default App;
ProductModal.js
import React from 'react';
class ProductModal extends React.Component {
constructor() {
super();
}
render() {
const 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">test</h4>
</div>
<div className="modal-body">
test
</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 ProductModal;
I am unsure what your issue is from your question but I am guessing your model doesn't open?
When you set state, you need to set it to the opposite of this.state.open
You can do it like this:
toggleModal() {
this.setState({
open: !this.state.open
});
}
I can't see where the modal is supposed to be rendered. You have to add it to render function of your "App" class. like this:
render() {
...
return(
<ProductModal open={true} />
...
):
}
and also, in your toggleModal function, do something like this:
this.setState({ open: !this.state.open});
Hope this solves the issue.
The issue is that you do not have your <ProductModal /> as a component in your <App /> In addition to setting your open state, once shown, it will (or should) never hide because you will not be able to toggle it again using your button, and you also do not have any keybindings within your <ProductModal /> itself.
I would suggest you bind an event listener within <ProductModal /> to
Check is ESC key is pressed
Bind a Cancel/Close button (in addition to a header x button).
Listen for if anywhere outside of your dialog is clicked, dismiss the modal.
You will also need to pass a handler from <App /> down to <ProductModal /> to notify when the modal has been closed.
In your App.js
handleClose() {
this.setState({
open: false
});
}
render() {
return (
...
<ProductModal open={this.state.open} handleClose={this.handleClose.bind(this)} />
)
}
Then in your ProductModal.js
handleClose() {
this.props.handleClose();
}
Observe the following using my sandbox:
https://stackblitz.com/edit/react-98m4cr
You'll see that I've implemented the handleClose event to control the state back up to the parent. In addition, you may want to add listeners as mentioned above, all triggering handleClose in the end; just remember to unbind them in ProductModal.js componentWillUnmount.

Resources