Opening modal from click of a different button from parent component - javascript

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

Related

How can I add a route on a modal using react.js?

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

ReactJS- render modal component on onclick event

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;

How ReactJS display fetch response onClick

I am trying to generate a random user information when pressing the button, and display the information above the button. In ProfilePanel.js, I created a avatar and user constants, which will use to show the information. In index.js, the avatar constant works for that since it doesn't need to use the Button. however, for user constant, it doesn't work. In below's code, I am fetching a api data to display user name, but it didn't show anything, I am not sure where wrong, is something wrong in Button.js or index.js. and how can I fix it. Can somebody help me out? Thanks.
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
import Panel from "./ProfilePanel";
import axios from 'axios';
import './index.css';
import Button from './Button';
const url = 'https://randomuser.me/api/';
class App extends Component {
constructor(props) {
super(props);
this.state = {
contacts: []
}
}
componentDidMount() {
this.fetchdata();
}
fetchdata() {
axios.get(url)
.then(res => {
console.log(res);
this.setState({ contacts: res.data.results});
});
}
render(){
const {contacts} = this.state;
return (
<div className="panel">
{contacts.map(contact => (
<div class="panel">
<Panel
key={contact.picture} avatar={contact.picture.medium}
/>
<li class="flex-container">
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
<Button title="location" onClick={this.fetchdata}>
</Button>
<Button key={contact.email} title="email">
</Button>
<Button key={contact.phone} title="phone">
</Button>
<Button key={contact.login.password} title="password">
</Button>
</li>
</div>
))}
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById("root")
);
ProfilePanel.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import './index.css';
import Button from './Button';
const style={
borderRadius: 150,
margin: 15,
}
class Panel extends Component {
render() {
const { avatar, user } = this.props;
return (
<div className="Panel">
<div class="panels">
<div className="avatar">
<img src={avatar} class="imageStyle" alt="" width={"200%"} height={"auto"}/>
</div>
</div>
<div class="center">
<h2 className="user">{user}</h2>
</div>
</div>
);
}
}
export default Panel;
Button.js
import './index.css';
import React, { Component } from 'react';
class Button extends Component {
constructor(props) {
super(props);
this.state = {
open:false,
};
}
render() {
const { title } = this.props;
const {open} = this.state;
return (
<button className={` ${open ? 'open' : ''}`}
class='button' onClick={(e) => this.handleClick(e)}>
<div className="panel-heading">
<h2 class='buttoncenter'>{title}</h2>
</div>
</button>
);
}
handleClick(e) {
e.preventDefault();
this.setState({
open: this.state.open
})
}
}
export default Button;
You're not changing state in the handle click. You need to set open to true;
handleClick(e) {
e.preventDefault();
this.setState({
open: true
})
}
You need to pass your user information in index.js. I think you have missed to pass the user props to the panel component, so that it shows the avatar alone. Without passing the users props, you are trying to destructure there in panel component.
//index.js should be like this
render(){
const {contacts} = this.state;
return (
<div className="panel">
{contacts.map(contact => (
<div class="panel">
<Panel
key={contact.picture} user={contact.name} avatar={contact.picture.medium}
/>
<li class="flex-container">
<Button title="name" >
<p key={contact.name} user={contact.name}></p>
</Button>
<Button title="location" onClick={this.fetchdata}>
</Button>
<Button key={contact.email} title="email">
</Button>
<Button key={contact.phone} title="phone">
</Button>
<Button key={contact.login.password} title="password">
</Button>
</li>
</div>
))}
</div>
);
}

React-Redux: Passing Event Handling inside map function

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>
)
}

React-Redux with Bootstrap -- modal component

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()}
}
});

Categories