Input control is not editable on Multi Modal of react-bootstrap - reactjs

I have two Modal Components in my application and on click of edit button in a Modal another Modal will open, and in the second Modal I have input control and its not editable
The following are the files which I used in my application.
import bootstrap css in index.js file as below
import 'bootstrap/dist/css/bootstrap.css'
App.js
function App() {
return (
<div>
<MyButton />
</div>
);
}
MyButton.js
export default class MyButton extends Component {
constructor(props) {
super(props);
this.state = {
personalInfoModalShow: false
};
}
render() {
let handlePersonalInfoModalHide = () => this.setState({
personalInfoModalShow: false
});
return (
<div>
<button className="btn btn-primary" onClick={() => this.setState({
personalInfoModalShow: true
})}
>
Open Modal
</button>
<PersonalInfoModal
show={this.state.personalInfoModalShow}
handlePersonalInfoModalHide={handlePersonalInfoModalHide}
/>
</div>
);
}
}
PersonalInfoModal.js
import React, {Component} from 'react';
import Modal from "react-bootstrap/Modal";
import {Container, Table} from "reactstrap";
import {FaPencilAlt} from "react-icons/fa";
import EditModal from "./EditModal";
export default class PersonalInfoModal extends Component {
constructor(props) {
super(props);
this.state = {
id: 100,
name: 'Sam',
department: 'IT',
isEditClicked: false,
editModalShow: false
};
}
render() {
let handleEditModalHide = () => this.setState({
isEditClicked: false,
editModalShow: false
});
return (
<div>
<Modal
show={this.props.show}
onHide={this.props.handlePersonalInfoModalHide}
size="lg"
centered
>
<Modal.Header closeButton>
<Modal.Title id="personal-modal-title">
Personal Information
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Container fluid>
<Table striped responsive size="sm" className="text-center mt-4">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Department</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>{this.state.id}</td>
<td>{this.state.name}</td>
<td>{this.state.department}</td>
<td>
<div onClick={() => this.setState({
isEditClicked: true,
editModalShow: true
})}
>
<FaPencilAlt />
</div>
{this.state.isEditClicked &&
<EditModal
show={this.state.editModalShow}
handleEditModalHide={handleEditModalHide}
department={this.state.department}
/>
}
</td>
</tr>
</tbody>
</Table>
</Container>
</Modal.Body>
</Modal>
</div>
);
}
}
EditModal.js
import React, {Component} from 'react';
import {Button, Modal} from "react-bootstrap";
export default class EditModal extends Component {
constructor(props) {
super(props);
this.state = {
department: props.department
};
}
handleChange = (e) => {
const input = e.target;
const name = input.name;
const value = input.value;
this.setState({[name]: value});
};
render() {
return (
<div>
<Modal
show={this.props.show}
onHide={this.props.handleEditModalHide}
size="sm"
centered
>
<Modal.Header closeButton>
<Modal.Title id="edit-modal-title">
Edit
</Modal.Title>
</Modal.Header>
<Modal.Body>
<input style={{width: "35%"}} type="text" value={this.state.department} name="department" onChange={this.handleChange} />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.props.handleEditModalHide}>
Close
</Button>
<Button variant="primary" onClick={() => alert("saved")}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div>
);
}
}

Related

Can't display bootstrap modal onClick

I have a problem to display the bootstrap modal in my react-website. Here is my code:
import React,{Component} from 'react';
import './restaurant.css';
import {connect} from "react-redux";
import {IoMdArrowBack} from 'react-icons/io';
import './restaurantMenu.css';
import DishDetailModal from "./dishDetailModal";
class RestaurantMenu extends Component{
renderDishes = (dishes)=>{
console.log(dishes);
return dishes.map((item,index)=>{
console.log(item);
{
if (item.isAvailable === true) {
return (
<div key={index} className="dishContainer">
<button className="dishButton" onClick={()=><DishDetailModal/>}>
<text style={{fontWeight: 'bold'}}>{item.name}</text>
<br/>
<text>{item.discription}</text>
<br/>
<text>{item.price} €</text>
</button>
</div>
)
}else{
return(
<div key={index} className="dishContainer">
<text style={{fontWeight: 'bold'}}>{item.dishTitle}</text>
<br/>
<text>{item.dishDescription}</text>
<br/>
<text>{item.dishPrice} €</text>
</div>
)
}
}
})
}
render(){
return(
<div style={{textAlign:'center'}}>
<br/>
<div className="backButtonClass">
<button
className="backButton"
onClick={this.props.showMenuFunction}
>
<IoMdArrowBack size={40}/>
</button>
</div>
<br/>
{this.renderDishes(this.props.requestedData[this.props.restaurantId].dishes)}
</div>
)
}
}
In the renderDishes-function I want to render return all the dishes and wrap each in a button that opens the modal with specific dish-information. My problem is that the modal doesn't show up onClick. Here is the modal-component:
import React,{Component} from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
export default class DishDetailModal extends Component{
constructor(props) {
super(props);
this.state={
show: true
}
}
handleModal = () =>{
this.setState({show: !this.state.show})
};
render(){
return (
<>
<Button variant="primary" onClick={()=>this.handleModal}>
Launch demo modal
</Button>
<Modal show={this.state.show} onHide={()=>this.handleModal}>
<Modal.Header closeButton>
<Modal.Title>Modal heading</Modal.Title>
</Modal.Header>
<Modal.Body>Woohoo, you're reading this text in a modal!</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={()=>this.handleModal}>
Close
</Button>
<Button variant="primary" onClick={()=>this.handleModal}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</>
);
}
}

Why this code has findDOMNode warning first time open the dialog?

Always got this error when the first time open this dialog:
Warning: findDOMNode is deprecated in StrictMode. findDOMNode was
passed an instance of Transition which is inside StrictMode. Instead,
add a ref directly to the element you want to reference
import React, { Component } from "react";
import {Button, Modal, Form} from "react-bootstrap";
class ClusterBar extends Component {
state = { show: false, clusterName: '', clusterConfigure: '' };
handleClose = () => this.setState({show: false});
handleShow = () => this.setState({show: true});
handleSave = () => {
this.setState({show: false});
console.log(this.state.clusterName, this.state.clusterConfigure);
}
handleClusterNameChange = (event) => {
this.setState({clusterName: event.target.value});
}
handleClusterConfigureChange = (event) => {
this.setState({clusterConfigure: event.target.value});
}
render() {
return(
<>
<div className="list-group">
<Button className="list-group-item list-group-item-action">cluster One</Button>
<Button className="list-group-item list-group-item-action">cluster Two</Button>
<Button className="list-group-item list-group-item-action">cluster Three</Button>
<Button className="list-group-item list-group-item-action" onClick={this.handleShow}>+</Button>
</div>
<Modal show={this.state.show} onHide={this.handleClose}>
<Modal.Header closeButton>
<Modal.Title>Add a cluster</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="formClusterName">
<Form.Label>Cluster Name</Form.Label>
<Form.Control type="text" onChange={this.handleClusterNameChange} />
</Form.Group>
<Form.Group controlId="formClusterConfigure">
<Form.Label>Connnection Configure</Form.Label>
<Form.Control as="textarea" rows="3" onChange={this.handleClusterConfigureChange} />
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.handleClose}>
Cancel
</Button>
<Button variant="primary" onClick={this.handleSave}>
Save
</Button>
</Modal.Footer>
</Modal>
</>
)
}
}
export default ClusterBar

How could I have a successful pop - up of dialog box?

My aim is to have my modal dialog box pop up on click. However, I receive this error every time I execute:
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem
May I have some direction on where I am going wrong with this?
import React from 'react';
import { connect } from 'react-redux';
import { myActions } from './actions/my.actions';
import { Modal, Button } from 'react-bootstrap';
class LoadTable extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
Search: "Search",
visible: false
}
this.doSearch = this.doSearch.bind(this);
this.handleShow = this.handleShow.bind(this);
this.handleClose = this.handleClose.bind(this);
this.runstuff = this.runstuff(this);
}
componentDidMount() {
this.props.getstuff()
.then((res) => {
this.setState({
data: res.results.response || [], <--IT shows in the error that it breaks here.
visible: false
})
});
}
doSearch(e) {
const { name, value } = e.target;
this.setState({ [name]: value });
console.log("Search");
}
handleShow() {
this.setState({ visible: true });
}
handleClose() {
this.setState({ visible: false });
}
runstuff() {
}
render() {
const { data, Search } = this.state;
return data.length > 0 ? (
<div className="row row-centered">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12 col-centered">
<div id="Search" className="row col-xs-5 col-lg-2">
<div className="form-group">
<input className='form-control' type="text" placeholder="Search" name="Search" value={Search} onChange={this.doSearch} autoFocus />
</div>
</div>
<table className="table table-striped">
<thead>
<tr>
<td>Name</td>
<td>stuff</td>
<td>Start</td>
<td>End</td>
<td>Status</td>
<td></td>
<td></td>
</tr>
</thead>
<tbody>
{
data.map((dt) => {
return (
<tr>
<td>{dt.name}</td>
<td>{dt.stuff}</td>
<td>{dt.start}</td>
<td>{dt.end}</td>
{ dt.status ?
<td>
<div className="alert alert-success" role="alert"></div>
</td>
:
<td>
<div className="alert alert-danger" role="alert"></div>
</td>
}
<td><button type="button" className="btn btn-primary" onClick={this.runStuff}>Run Stufff</button></td>
<td><button type="button" className="btn btn-info" onClick={this.displayLog}><View Stuff</button></td>
<Modal
show={this.state.visible}
onHide={this.handleClose}
>
<Modal.Header closeButton>
<Modal.Title>Run Stuff for Stuff</Modal.Title>
</Modal.Header>
<Modal.Body>
<div>{dt.lotsofstuff}</div>
</Modal.Body>
<Modal.Footer>
<Button
variant="secondary"
onClick={this.handleClose}
>
Close
</Button>
<Button variant="primary" onClick={this.handleClose}>
Download
</Button>
</Modal.Footer>
</Modal>
</tr>
);
})
}
</tbody>
</table>
</div>
</div>
) :
<div className="row">
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>No Data to Display at the moment</p>
</div>
</div>;
}
}
function mapStateToProps(state) {
return {
};
}
const mapDispatchToProps = dispatch => ({
getstuff: () => dispatch(myActions.getstuff())
});
export default connect(mapStateToProps, mapDispatchToProps)(myLoad);

React bootstrap modal not rendering updated data

When I'm running the below code and clicking the "Read" button, data is not updating in modal window even though I have few different components rendered.
I'm new to react, I have read similar posts that it has something to do with changing state but don't really know how to apply it in this case?
import React, { Component } from "react";
import Moment from "react-moment";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import ButtonToolbar from "react-bootstrap/ButtonToolbar";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import Container from "react-bootstrap/Container";
import CardDeck from "react-bootstrap/CardDeck";
import Modal from "react-bootstrap/Modal";
import "./posts.css";
const config = require("../../config").config();
class MyVerticallyCenteredModal extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
{this.props.title}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<pre>{this.props.title}</pre>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.props.onHide}>Close</Button>
</Modal.Footer>
</Modal>
);
}
}
This is my parent component where I'm having button opening modal, post.title and post.body is not being updated on modal.
class Posts extends Component {
constructor() {
super();
this.state = {
posts: [],
modalShow: false
};
}
componentDidMount() {
fetch(config.localhostPrefix + "/api/stories")
.then(res => res.json())
.then(posts => this.setState({ posts }));
}
render() {
let modalClose = () => this.setState({ modalShow: false });
return (
<div className="Posts">
<h2>Posts</h2>
<CardDeck>
{this.state.posts.map(post => (
<Card key={post._id}>
<Card.Body>
<Card.Title>"{post.title}"</Card.Title>
<Card.Text>
{post.body}
<ButtonToolbar>
<Button
variant="primary"
onClick={() => this.setState({ modalShow: true })}
>
Read
</Button>
<MyVerticallyCenteredModal
show={this.state.modalShow}
title={post.title}
body={post.body}
onHide={modalClose}
/>
</ButtonToolbar>
</Card.Text>
</Card.Body>
<Card.Footer>
<Container>
<Row>
<Col>
<small className="text-muted">
Created:
<Moment format=" YYYY/MM/DD hh:mm">
{post.createdAt}
</Moment>{" "}
</small>
</Col>
</Row>
<Row>
<Col>
<small className="text-muted">
Updated:
<Moment format=" YYYY/MM/DD hh:mm">
{post.updatedAt}
</Moment>
</small>
</Col>
</Row>
<Row>
<Col>
<small className="text-muted">
Author: {post.author}{" "}
</small>
</Col>
</Row>
</Container>
</Card.Footer>
</Card>
))}
</CardDeck>
</div>
);
}
}
export default Posts;
Thanks for creating the sandbox. I was able to fix the issue you're having. I slightly modified your Posts component. You were close but had one or two things you missed out. Please see my changes below:
class Posts extends Component {
constructor() {
super();
this.state = {
posts: [
{ _id: 1, title: "title1", body: "body1", author: "author1" },
{ _id: 2, title: "title2", body: "body2", author: "author2" },
{ _id: 3, title: "title3", body: "body3", author: "author3" }
],
postId: null,
modalShow: false
};
}
modalClose = id => {
this.setState({ modalShow: !this.state.modalShow, postId: id });
};
renderModal = () => {
const { modalShow, postId, posts } = this.state;
const post = posts.find(post => (post._id === postId));
return (
<MyVerticallyCenteredModal
show={modalShow}
title={post.title}
body={post.body}
onHide={this.modalClose}
/>
);
};
render() {
return (
<div className="Posts">
<h2>Posts</h2>
<CardDeck>
{this.state.posts.map(post => (
<Card key={post._id + post.title}>
<Card.Body>
<Card.Title>"{post.title}"</Card.Title>
<Card.Text>
{post.body}
<ButtonToolbar>
<Button
variant="primary"
onClick={() => this.modalClose(post._id)}
>
Read
</Button>
</ButtonToolbar>
</Card.Text>
</Card.Body>
<Card.Footer>
<Container>
<Row>
<Col>
<small className="text-muted">
Author: {post.author}{" "}
</small>
</Col>
</Row>
</Container>
</Card.Footer>
</Card>
))}
</CardDeck>
{this.state.modalShow && this.renderModal()}
</div>
);
}
}
I hope this helps you.
It is not perfect but something to help you figure out what was wrong initially.

React-bootstrap Modal component opens/closes all modals when I map through a list

New to programming so I'm sorry if I'm not wording this correctly. I'm using a .map to render and list every single item on an array. For each item, I want the modal to open/close only the specific modal corresponding to each item in the array. However, when I click on the button to open the modal, every single one opens and closes. I believe this is because the modals are all set to an on/off button together. How can I set it it (with the .map value.id or something) so that only the specific modal opens and closes?
class DrinkMenu extends Component {
constructor(props, context) {
super(props, context);
this.state = {
show: false
};
this.handleHide = this.handleHide.bind(this);
}
handleHide() {
this.setState({ show: false });
}
async componentDidMount() {
let res = await axios.get('/getAllDrinks')
this.props.updateDrinkMenu(res.data)
}
async addToCart(drinkObj) {
let res = await axios.post('/addToCart', drinkObj)
console.log(`Added ${drinkObj.name} to order.`)
}
render() {
let drinkList = this.props.drinkMenu.map((drink) => {
return (
<div key={drink.id}>
<h5>{drink.name}</h5>
<h6>${drink.price}</h6>
<span
onClick={() => this.setState({ show: true })}
>
<strong>More Info</strong>
<br />
<button onClick={() => this.addToCart(drink)}>Add to Order</button>
</span>
<Modal
show={this.state.show}
onHide={this.handleHide}
container={this}
aria-labelledby="contained-modal-title"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title">
{drink.name}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>{drink.sub_category} | ABV {drink.abv}% | {drink.origin}</p>
<Col xs={6} md={4}>
<Image className="drink-logo" src={drink.logo} thumbnail />
</Col>
<p className="drink-description"><strong>Description</strong><br />{drink.description}</p>
<p href={drink.website}>Website</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.handleHide}>Close</Button>
</Modal.Footer>
</Modal>
</div>
)
})
return (
<div>
<h2>Drink Menu</h2>
<div>
{drinkList}
</div>
</div>
)
}
}
From the code you have shared, I see that you are handling all the Model with the same state value, i.e. show. This is causing all the state for all the Models to be true hence all of them as shown.
To solve this, you can extract your whole component in a new React class which has just the functionality to show Modal as per the independent state. So your new React component will look something like this:
class DrinkComponent extends React.Component {
constructor(props) {
super(props);
this.handleHide = this.handleHide.bind(this);
this.state = {
show: false,
}
}
handleHide() {
this.setState({ show: false });
}
render() {
const { drink } = this.props;
return (<div key={drink.id}>
<h5>{drink.name}</h5>
<h6>${drink.price}</h6>
<span
onClick={() => this.setState({ show: true })}
>
<strong>More Info</strong>
<br />
<button onClick={() => this.props.addToCart(drink)}>Add to Order</button>
</span>
<Modal
show={this.state.show}
onHide={this.handleHide}
container={this}
aria-labelledby="contained-modal-title"
>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title">
{drink.name}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>{drink.sub_category} | ABV {drink.abv}% | {drink.origin}</p>
<Col xs={6} md={4}>
<Image className="drink-logo" src={drink.logo} thumbnail />
</Col>
<p className="drink-description"><strong>Description</strong><br />{drink.description}</p>
<p href={drink.website}>Website</p>
</Modal.Body>
<Modal.Footer>
<Button onClick={this.handleHide}>Close</Button>
</Modal.Footer>
</Modal>
</div>);
}
}
In this case, each DrinkComponent will have its independent state of showing and hiding of the model. Now we have to just modify your existing render function in DrinkMenu, to display DrinkComponent. So your render function will look something like this:
render() {
let drinkList = this.props.drinkMenu.map((drink) => (<DrinkComponent drink={drink} addToCart={this.addToCart}/>));
return (
<div>
<h2>Drink Menu</h2>
<div>
{drinkList}
</div>
</div>
)
}
Also you can remove the show state from DrinkMenu as it wont be needed there.
Hope it helps.

Resources