I am trying to add ReactStrap Modal to my NavBar but couldn't find solution to it. I created a handler function which will be called upon click event but I am not able to call my login component on this handler function. I also bind the handler to the current DOM. What i have done is simply called Login component which is not working. Please explain how can I call component form this parent component
Code:
login.js
import React from 'react';
import {
Button,
Form,
FormGroup,
// FormText,
Label,
Input,
Modal,
ModalHeader,
ModalBody,
ModalFooter
} from 'reactstrap';
class Login extends React.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>
<Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Login</ModalHeader>
<ModalBody>
<Form>
<FormGroup>
<Label for="Email">Email</Label>
<Input type="email" name="email" id="email" placeholder=""/>
</FormGroup>
<FormGroup>
<Label for="password">Password</Label>
<Input type="password" name="password" id="password" placeholder=""/>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Submit</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default Login;
NavBar.js:
import React from 'react';
import Login from './login/login';
import {
Navbar,
NavbarBrand,
NavbarToggler,
Nav,
NavItem,
NavLink,
Collapse,
UncontrolledDropdown,
DropdownMenu,
DropdownItem,
DropdownToggle
} from 'reactstrap';
class NavbarComponent extends React.Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
isOpen: false
};
this.handleClick = this.handleClick.bind(this);
**this.setState={
isloggedOn: true
}**
}
stickyNavbar() {
var Navbar = document.getElementById("Navbar");
console.log(Navbar);
var sticky = Navbar.offsetTop;
if (window.pageYOffset >= sticky) {
Navbar.classList.add("sticky")
} else {
Navbar.classList.remove("sticky");
}
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
handleClick() {
**if(this.isloggedOn) {
return <Login/>;
}**
}
render() {
return (
<div>
<Navbar color="dark" light expand="md">
<NavbarBrand href="/">found-Missing</NavbarBrand>
<NavbarToggler onClick={this.toggle} />
<DropdownMenu right>
<DropdownItem onClick= {this.handleClick}>
Login
</DropdownItem>
<DropdownItem href="https://github.com/reactstrap/reactstrap">
Signup
</DropdownItem>
<DropdownItem divider />
<DropdownItem>
Reset
</DropdownItem>
</DropdownMenu>
</Navbar>
</div>
)
}
}
export default NavbarComponent;
If you are wanting to trigger the modal from within NavBar, simply add a prop to <NavBar /> that toggles modal within the state of login.js.
There are a few things wrong with your code.
The isLoggedOn in your NavBarComponent should reside in the state. You have put it in setState.
Your handleClick method is returning a react component. This is not right. It should just take care of toggling the state.
As others have said, you need to use conditional rendering.
With all these changes, your NavBarComponent should look like this:
import React from 'react';
import Login from './login/login';
import {
Navbar,
NavbarBrand,
NavbarToggler,
Nav,
NavItem,
NavLink,
Collapse,
UncontrolledDropdown,
DropdownMenu,
DropdownItem,
DropdownToggle
} from 'reactstrap';
class NavbarComponent extends React.Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
isOpen: false,
isLoggedOn: false
};
this.handleClick = this.handleClick.bind(this);
}
stickyNavbar() {
var Navbar = document.getElementById("Navbar");
console.log(Navbar);
var sticky = Navbar.offsetTop;
if (window.pageYOffset >= sticky) {
Navbar.classList.add("sticky")
} else {
Navbar.classList.remove("sticky");
}
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
handleClick() {
this.setState({ isLoggedOn: true })
}
render() {
return (
<div>
<Navbar color="dark" light expand="md">
<NavbarBrand href="/">found-Missing</NavbarBrand>
<NavbarToggler onClick={this.toggle} />
{this.state.isLoggedOn ? <div>User successfully logged in!!</div> : (
<DropdownMenu right>
<DropdownItem onClick= {this.handleClick}>
Login
</DropdownItem>
<DropdownItem href="https://github.com/reactstrap/reactstrap">
Signup
</DropdownItem>
<DropdownItem divider />
<DropdownItem>
Reset
</DropdownItem>
</DropdownMenu>
)}
</Navbar>
</div>
)
}
}
export default NavbarComponent;
Alright I have solved the issue.
I created a state in my component and passed that state to my component along with the method(which changes the current state on onclick event) from which component can access it from parent component.
Once the component renders modal, it will call loginmodals method of parent component and change the current state and return the current state to parent component.
Now current state is false, again Parent component will call login component with new state i.e. false on which Modal will look at the state which is false, so it will close the Modal.
Login.js:
import React from 'react';
import {
Button,
Form,
FormGroup,
Label,
Input,
Modal,
ModalHeader,
ModalBody,
ModalFooter
} from 'reactstrap';
class Login extends React.Component {
constructor(props) {
console.log(props);
super(props);
}
render() {
return (
<div onClick={this.props.loginmodals}>
{/* <Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button> */}
<Modal isOpen={this.props.loginmodal} toggle={this.props.loginmodals} className={this.props.className}>
<ModalHeader toggle={this.props.loginmodals}>Login</ModalHeader>
<ModalBody>
<Form>
<FormGroup>
<Label for="Email">Email</Label>
<Input type="email" name="email" id="email" placeholder=""/>
</FormGroup>
<FormGroup>
<Label for="password">Password</Label>
<Input type="password" name="password" id="password" placeholder=""/>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Submit</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default Login;
Navbar.js:
import React from 'react';
import Login from './login/login';
import {
Navbar,
NavbarBrand,
NavbarToggler,
Nav,
NavItem,
NavLink,
Collapse,
UncontrolledDropdown,
DropdownMenu,
DropdownItem,
DropdownToggle
} from 'reactstrap';
class NavbarComponent extends React.Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
isOpen: false,
loginmodal: false,
signupmodal: false
};
this.loginmodals = this.loginmodals.bind(this);
}
toggle() {
this.setState({
isOpen: !this.state.isOpen
});
}
loginmodals(state) {
this.setState({
loginmodal: !this.state.loginmodal,
});
}
render() {
return (
<div>
<Navbar color="" light expand="md">
<NavbarBrand href="/">found-Missing</NavbarBrand>
<NavbarToggler onClick={this.toggle} />
<Collapse isOpen={this.state.isOpen} navbar>
<Nav className="ml-auto" navbar>
<NavItem>
<NavLink href="/components/">About us</NavLink>
</NavItem>
<NavItem>
<NavLink href="https://github.com/reactstrap/reactstrap">How it Works</NavLink>
</NavItem>
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
login/signup
</DropdownToggle>
<DropdownMenu right>
**<DropdownItem onClick={this.loginmodals}>
Login
<Login loginmodal={this.state.loginmodal} loginmodals={this.loginmodals}/>
</DropdownItem>**
<DropdownItem divider />
<DropdownItem>
Reset
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</Collapse>
</Navbar>
</div>
)
}
}
export default NavbarComponent;
Related
I am fairly new to react and am having an issue. I am using reactstrap to call a modal on click of a button. In reactstrap docs the modal is called on the click of a button in the modal component like so:
import React from 'react';
import { Button, Modal, ModalFooter, ModalHeader, ModalBody } from 'reactstrap';
class SubmitConfirmation extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
fade: true,
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal,
fade: !this.state.fade,
});
}
render() {
return (
<div>
<Button color="danger" onClick={this.toggle}>
TOGGLE
</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle} fade={this.state.fade} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
<ModalBody></ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>
Do Something
</Button>{' '}
<Button color="secondary" onClick={this.toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
export default SubmitConfirmation;
I want to call the modal from the click of a button in a parent component How do I do this?
export default class SampleApp extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
return (
<div>
<Button
color="primary"
size="sm"
style={{ width: '100%' }}
onClick={this.toggle}
Submit
</Button>
</div>
)
}
}
How do I call the button from parent component:
You will need to move the state to the parent component to get this functionality,
Parent Component:
import React from "react";
import { Button } from "reactstrap";
import Child from "./Child";
export default class SampleApp extends React.Component {
constructor(props) {
super(props);
this.state = { modal: false, fade: true };
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({
modal: !this.state.modal,
fade: !this.state.fade
});
}
render() {
return (
<>
<Button
color="primary"
size="sm"
style={{ width: "100%" }}
onClick={this.toggle}
>
Open
</Button>
<Child
modal={this.state.modal}
toggle={this.toggle}
fade={this.state.fade}
/>
</>
);
}
}
Child Component
import React from "react";
import { Button, Modal, ModalFooter, ModalHeader, ModalBody } from "reactstrap";
class SubmitConfirmation extends React.Component {
render() {
return (
<Modal
isOpen={this.props.modal}
toggle={this.props.toggle}
fade={this.props.fade}
className={this.props.className}
>
<ModalHeader toggle={this.toggle}>Modal title</ModalHeader>
<ModalBody></ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>
Do Something
</Button>{" "}
<Button color="secondary" onClick={this.toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
);
}
}
export default SubmitConfirmation;
It seems like you forgot to add this.props.toggle
<div>
<Button
color="primary"
size="sm"
style={{ width: '100%' }}
onClick={this.props.toggle}
Submit
</Button>
</div>
Since you are passing toggle function through props, the function belongs to this.props property of your component, just like any other property you pass to child component through props
I am using React.js but I don't achieve to switch modal. Here is my code :
import React from "react";
import ReactDOM from "react-dom";
import moment from "moment";
import { Modal, version, Button } from "antd";
import "antd/dist/antd.css";
import { BrowserRouter, Link, Redirect, Route, Switch } from "react-router-dom";
import Clickthere from "Clickthere";
class App extends React.Component {
state = { visible: false };
showModal = () => {
this.setState({
visible: true
});
};
handleOk = (e) => {
console.log(e);
this.setState({
visible: false
});
};
handleCancel = (e) => {
console.log(e);
this.setState({
visible: false
});
};
render() {
return (
(
<div>
<Button type="primary" onClick={this.showModal}>
Open
</Button>
<Modal
title="Basic Modal"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
<p style={{ textAlign: "center" }}>
Other thing?{" "}
<BrowserRouter>
<Link to="/clickthere">
<i className="fas fa-user-plus" /> Click there
</Link>
</BrowserRouter>
</p>
</Modal>
</div>
),
(
<BrowserRouter>
<Switch>
<Route path="/clickthere" component={Clickthere} />
</Switch>
</BrowserRouter>
)
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
I achieve to open the first modal but I don't achieve when I click on "Click there" nothing happen...
Here is the code of the component Clickthere :
import { Modal } from "react-bootstrap";
import React from "react";
import { BrowserRouter, Switch } from "react-router-dom";
const Clickthere = (props) => {
console.log(props);
return (
<>
<Modal>
<div>
<p>This is a test.</p>
</div>
</Modal>
<BrowserRouter>
<Switch></Switch>
</BrowserRouter>
</>
);
};
export default Clickthere;
Do you know why it does not work ?
Thank you very much !
Here is my code : My code
I'm new to React. I'm building up an app in which MainComponent is the container component and MenuComponent and DishDetail are the presentation components.
When I'm running the code in the browser it is showing cannot read property 'map' for undefined in MenuComponent at line 11.
I have checked it and have done it as instructed in my lecture but still facing this problem. I'm attaching all the files here :
MainComponent:
import React, { Component } from 'react';
import { Navbar, NavbarBrand } from 'reactstrap';
import Menu from './MenuComponent';
import DishDetail from './DishdetailComponent';
import { DISHES } from '../shared/dishes';
class Main extends Component {
constructor(props) {
super(props);
this.state = {
dishes: DISHES,
selectedDish : null
};
}
onDishSelect(dishId) {
this.setState({ selectedDish: dishId});
}
render() {
return (
<div>
<Navbar dark color="primary">
<div className="container">
<NavbarBrand href="/">Ristorante Con Fusion</NavbarBrand>
</div>
</Navbar>
<Menu dishes={this.state.dishes} onClick={(dishId) => this.onDishSelect(dishId)} />
<DishDetail selectedDish={this.state.dishes.filter((dish) => dish.id === selectedDish(dishId))[0]} />
</div>
);
}
}
export default Main;
MenuComponent :
import React, { Component } from 'react';
// import { Media } from 'reactstrap';
import { Card, CardImg, CardImgOverlay, CardText, CardBody,CardTitle } from 'reactstrap';
class Menu extends Component {
constructor(props) {
super(props);
}
render() {
const menu = this.props.dishes.map((dish) => {
return(
<div key={dish.id} className="col-12 col-md-5 m-1">
{/* <Media tag="li">
<Media left middle>
<Media object src={dish.image} alt={dish.name} />
</Media>
<Media body className="ml-5">
<Media heading>{dish.name}</Media>
<p>{dish.description}</p>
</Media>
</Media> */}
<Card key={dish.id} onClick={() => this.props.onDishSelect(dish.id)}>
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
);
});
return(
<div className="container">
<div className="row">
{/* <Media list>
{menu}
</Media> */}
{menu}
</div>
</div>
);
}
}
export default Menu;
That's basically saying that the value from this.props.dishes is undefined.
Make sure that the value that you're importing below is an array (and it's valid).
import { DISHES } from '../shared/dishes';
Also, you can use the DISHES variable directly instead of storing it into the state, like this:
<Menu dishes={DISHES} onClick={(dishId) => this.onDishSelect(dishId)} />
New to React/Redux, I am having hard time implementing on event handling.
I know that the 'this' reference key goes null when passed into the map (this.props.addRecipe.map of recipebox) function but I don't how to resolve it.
Essentially I would like to pass the onChange handler to ModalBox for each element in the array.
src/containers/recipebox
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ListGroup, ListGroupItem, Panel, Button, Modals } from 'react-bootstrap';
import MyModal from '../components/mymodal';
import { bindActionCreators } from 'redux';
import { deleteRecipe } from '../actions/index';
import shortid from 'shortid'
import ModalBox from '../containers/modalbox'
class RecipeBox extends Component {
constructor(props){
super(props);
this.renderRecipeList = this.renderRecipeList.bind(this)
this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
}
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
}
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
}
renderRecipeList(recipeItem, index){
const recipe = recipeItem.recipe;
const ingredients = recipeItem.ingredients;
const id = shortid.generate();
return(
<div key={id}>
<Panel bsStyle="primary" collapsible header={<h3>{recipe}</h3>}>
<ListGroup >
<ListGroupItem header="Ingredients"></ListGroupItem>
{ingredients.map(function(ingredient,index){
return <ListGroupItem key={index}>{ingredient}</ListGroupItem>;
})}
<ListGroupItem>
<Button
onClick={() => this.props.deleteRecipe(recipeItem)}
bsStyle="danger">Delete
</Button>
<ModalBox
modalTextTitle={'Edit Recipe'}
recipeName={recipe}
userIngredients={ingredients}
handleRecipeNameChange={this.handleRecipeNameChange}
handleUserIngredientsChange={this.handleUserIngredientsChange}
onClickSubmit={this.onClickSubmit}
/>
</ListGroupItem>
</ListGroup>
</Panel>
</div>
)
}
render(){
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(this.renderRecipeList)}
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
addRecipe : state.recipeState
};
}
function mapDispatchToProps(dispatch){
return bindActionCreators({deleteRecipe : deleteRecipe}, dispatch)
}
export default connect(mapStateToProps,mapDispatchToProps)(RecipeBox);
src/containers/modalbox
import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
class ModalBox extends Component {
constructor(props){
super(props)
this.state = {
showModal: false
};
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal(){
this.setState({
showModal: !this.state.showModal
});
}
submitData(link){
link()
this.toggleModal()
}
render() {
return (
<div>
<Button
bsStyle="info"
onClick={this.toggleModal}
>
{this.props.modalTextTitle}
</Button>
<Modal show={this.state.showModal} onHide={this.toggleModal}>
<Modal.Header closeButton>
<Modal.Title>{this.props.modalTextTitle}</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={this.props.recipeName}
onChange= {this.props.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
value={this.props.userIngredients}
onChange={this.props.handleUserIngredientsChange}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={ () => this.submitData(this.props.onClickSubmit) }>
{this.props.modalTextTitle}
</Button>
<Button
bsStyle="danger"
onClick= {this.toggleModal}
>Close</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}
export default ModalBox
inside map function you need to change the this like below code,
render(){
const self = this;
return(
<div className="container">
<div className='panel-group'>
{this.props.addRecipe.map(self.renderRecipeList)}
</div>
</div>
)
}
I'm having hard time applying the concept between components vs containers using Bootstrap's modal in React-Redux.
Essentially, instead of re-creating specific modals, I'd like to create a React Component that holds a modal template.
To illustrate my example, here's a FCC project that I'd like to implement:
https://codepen.io/FreeCodeCamp/full/xVXWag/
The "Add Recipe" and "Edit" has the same component, yet when being called it is used by different containers (is this correct mindset?).
I have the following code in one of my container for "Add Recipe":
import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
import { addRecipe } from '../actions/index';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
class AddRecipeButton extends Component{
constructor(props){
super(props);
this.state = {recipeName: '', userIngredients: '', showModal: false};
this.close = this.close.bind(this);
this.open = this.open.bind(this);
this.onClickSubmit = this.onClickSubmit.bind(this);
this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
}
close() {
this.setState({ showModal: false, recipeName: '', userIngredients: '' });
}
open() {
this.setState({ showModal: true });
}
onClickSubmit(){
const splitIngredients = this.state.userIngredients.split(/[ ,]+/)
this.props.addRecipe([this.state.recipeName, splitIngredients])
this.setState({ showModal: false, recipeName: '', userIngredients: '' });
}
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
}
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
}
render(){
const centerText = {
textAlign : 'center'
}
return(
<div>
<Button
bsStyle="success"
onClick={this.open}
>Add Recipe
</Button>
<Modal show={this.state.showModal} onHide={this.close}>
<Modal.Header closeButton>
<Modal.Title style={centerText}>Add Recipe</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={this.state.recipeName}
onChange={this.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
onChange = {this.handleUserIngredientsChange}
value={this.state.userIngredients}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={this.onClickSubmit}>Add Recipe
</Button> <Button
bsStyle="danger"
onClick={this.close}>Close
</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({addRecipe}, dispatch)
}
export default connect(null,mapDispatchToProps)(AddRecipeButton)
Although this works, I can already tell that the render function should call a component that does the actual rendering of the modal instead.
I guess my question is how to create the modal component and keep track of the modal window state?
EDIT:
Those who are curious, I was able to implement what it worked for me.
Modal Component:
import React, { Component } from 'react'
import { Button, Modal } from 'react-bootstrap';
export default (props) => {
return (
<Modal show={props.showModal} onHide={props.toggleModal}>
<Modal.Header closeButton>
<Modal.Title>{props.title}</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={props.recipeName}
onChange={props.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
onChange = {props.handleUserIngredientsChange}
value={props.userIngredients}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={props.onClickSubmit}>Add Recipe
</Button> <Button
bsStyle="danger"
onClick={props.toggleModal}>Close
</Button>
</Modal.Footer>
</Modal>
)
}
Add Recipe Button Container (smart component)
import React, { Component } from 'react';
import { Button, Modal } from 'react-bootstrap';
import { addRecipe } from '../actions/index';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import MyModal from '../components/mymodal';
class AddRecipeButton extends Component{
constructor(props){
super(props);
this.state = {
recipeName: '',
userIngredients: '',
showModal: false
};
this.onClickSubmit = this.onClickSubmit.bind(this);
this.handleRecipeNameChange = this.handleRecipeNameChange.bind(this)
this.handleUserIngredientsChange = this.handleUserIngredientsChange.bind(this)
this.toggleModal = this.toggleModal.bind(this);
}
toggleModal(){
this.setState({
showModal: !this.state.showModal
});
}
onClickSubmit(){
const splitIngredients = this.state.userIngredients.split(/[ ,]+/)
this.props.addRecipe([this.state.recipeName, splitIngredients])
this.toggleModal()
}
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
}
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
}
render(){
return (
<div>
<Button
bsStyle="success"
onClick={this.toggleModal}
>Add Recipe
</Button>
<MyModal
toggleModal={this.toggleModal}
showModal={this.state.showModal}
recipeName={this.state.recipeName}
userIngredients={this.state.userIngredients}
handleRecipeNameChange={this.handleRecipeNameChange}
handleUserIngredientsChange={this.handleUserIngredientsChange}
onClickSubmit={this.onClickSubmit}
/>
</div>
)
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators({addRecipe}, dispatch)
}
export default connect(null,mapDispatchToProps)(AddRecipeButton)
Something like this would work (kind of a quick job but you get the idea..?)
// Create a React component for your modal:
var MyModal = React.createClass({
render: function() {
return (
<Modal onHide={this.props.handleToggle}>
<Modal.Header closeButton>
<Modal.Title style={centerText}>Add Recipe</Modal.Title>
</Modal.Header>
<Modal.Body>
<form>
<div className="form-group">
<label htmlFor="recipeName">Name of Recipe:</label>
<input
value={this.props.recipeName}
onChange={this.props.handleRecipeNameChange}
type="text"
className="form-control"
id="recipeName" />
</div>
<div className="form-group">
<label htmlFor="userIngredients">Ingredients:</label>
<textarea
placeholder="you can seperate by comma"
onChange = {this.props.handleUserIngredientsChange}
value={this.props.userIngredients}
type="text"
className="form-control"
id="userIngredients" />
</div>
</form>
</Modal.Body>
<Modal.Footer>
<Button
bsStyle="info"
onClick={this.props.onClickSubmit}>Add Recipe
</Button> <Button
bsStyle="danger"
onClick={this.props.handleToggle}>Close
</Button>
</Modal.Footer>
)
}
});
// Return modal in render function and pass parent components state and functions down through props:
var AddRecipeButton = React.createClass({
getInitialState: function() {
return {
isModalOpen: false,
recipeName: '',
userIngredients: ''
};
},
toggleModal: function() {
this.setState({
isModalOpen: !this.state.isModalOpen
});
},
onClickSubmit(){
const splitIngredients = this.state.userIngredients.split(/[ ,]+/)
this.props.addRecipe([this.state.recipeName, splitIngredients])
this.toggleModal();
},
handleRecipeNameChange(event){
this.setState({recipeName: event.target.value})
},
handleUserIngredientsChange(event){
this.setState({userIngredients: event.target.value})
},
renderModal: function() {
if (this.state.isModalOpen) {
return
<MyModal
toggleModal={this.toggleModal}
onClickSubmit={this.onClickSubmit}
handleRecipeNameChange={this.handleRecipeNameChange}
handleUserIngredientsChange={this.handleUserIngredientsChange}
/>;
}
},
render: function() {
{this.renderModal()}
}
});