ReactJs bootstrap modal with dynamic body - javascript

I am working on a website where login, register and forgot password popups will appear alternatively (not at a time). So I want to create a modal with multiple body content components.
But I am unable to figure out how to display those. When I click on login or register button Modal content is attaching to modal, but not displaying
Footer.js
import React, { Component } from 'react'
import ModalTemplate from './modals/ModalTemplate'
class Footer extends React.Component {
render() {
return (<><ModalTemplate /></>)
}
}
export default Footer
Footer.js
import React, { Component } from 'react'
import ReactDOM from "react-dom"
import LoginModalBody from './modals/LoginModalBody'
import RegisterModalBody from './modals/RegisterModalBody'
class Header extends Component {
Login() {
ReactDOM.render(<LoginModalBody />, document.getElementById('common_modal_content'));
}
Register() {
ReactDOM.render(<RegisterModalBody />, document.getElementById('common_modal_content'));
}
render() {
return (
<div className='fd bg_Header height_100vh p_5'>
<div className='mainSize'>
<div className="fd">
<div className="row m_0 p_tb_15">
<div className="col-sm-4 col-md-4">
<img className="logoSize" src={Constants.Application.PUB_URL + "/img/logo.svg"} />
<img src={Constants.Application.PUB_URL + "/img/icons/menu.svg"} className="float-right m_r_15 pointer menuIcn"
width="30px" />
</div>
<div className="col-sm-8 col-md-8">
<span className="pointer" onClick={this.Login}>LOGIN
</span> | <span className="pointer" onClick={this.Register}>REGISTER </span>
</div>
</div>
</div>
</div>
)
}
}
export default Header
ModalTemplate.js
import React, { Component } from 'react'
class ModalTemplate extends React.Component {
render() {
return (<> <div id="common_modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog">
<div class="modal-content" id="common_modal_content">
</div>
</div>
</div></>);
}
}
export default ModalTemplate;
LoginModalBody .js
import React, { Component } from 'react'
class LoginModalBody extends React.Component {
showModal() {
document.getElementById('common_modal').classList.add('in')
document.getElementById('common_modal').classList.add('show')
}
hideModal() {
document.getElementById('common_modal').classList.remove('in')
document.getElementById('common_modal').classList.add('hide')
}
componentDidMount() {
this.showModal();
}
render() {
return (<>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<div className="fd">
<h6 className="p_t_15"><b>Log in continue</b></h6>
<input type="text" placeholder="Email address"
className="fd m_t_15 form-control bck_ligrey bdr_0" />
<input type="text" placeholder="Password"
className="fd m_t_15 form-control bck_ligrey bdr_0 brdr_grey" />
<div className="fd m_t_15">
<input type="checkbox" />
<font color="#ddd">Remember My password</font>
<p className="float-right font-12 m_0">Show password</p>
</div>
<button type="button" className="btn fd btn_orng font-12 m_tb_10"> Log in</button>
<div className="fd p_b_15 text-center">
<u><b>Forgot password?</b></u>
</div>
<p className="fd m_b_10 m_t_30 text-center"><span className="font-10">Don't have an account?</span> <b>Sign Up</b></p>
</div>
</div>
</>
);
}
}
export default LoginModalBody;

Add your modal component in separate file and import that in Footer or Header.
const [content, setContent] = useState(); State for your content.
You need to create a function that will define which modal content you want to display. You can pass type as follows: `onClick={() => callModalComponent('login')}
Your function will be like:
const callModalComponent = (type: string) => {
if(type === 'login'){
setContent(<LoginComponent />) // set state content as per your form requirement
} else if(type === 'register'){
setContent(<RegisterComponent />)
}
openModalContainer() // this will open your modal.
}

Related

I have made a card and I want to loop the whole card component

I have made 1 card component. Here I want to loop through it, So that I can Use it again and again.
/* CardUI.jsx*/
import React from "react";
import img1 from "../assets/raj.jpg";
import "./Cards.css";
import { FaTshirt, FaLocationArrow } from "react-icons/fa";
import { BsGeoAlt } from "react-icons/bs";
import { GiTakeMyMoney } from "react-icons/gi";
import { MdEventAvailable } from "react-icons/md";
import { IoLogoDesignernews } from "react-icons/io5";
let skills=["Python","mongos","Java"]
/Here I want to loop through Card, so that I can make several card. How Can I achieve that. I Want to achieve loop, so that I do not have to re render card again and again. Here card is the functional component./
const Card= (props) => {
return (
<div className="card container">
<div className="card-body row">
<img src={img1} style={{marginRight:"10px",paddingRight:"10px"}} className="image col-sm-2" alt="raj" />
<div className="col-md-6" style={{textAlign:"left",marginLeft:"-5px",marginRight:"10px",paddingRight:"80px",paddingLeft:"0px"}}>
<h5 style={{ font: "1px",marginBottom:"0px"}}>{props.name}</h5>
<p style={{ font: "0px",marginTop:"0px"}}><MdEventAvailable/> {props.current_availability}</p>
</div>
<h5 className="Rating col-sm-2">9.5</h5>
</div>
<div id="box" className="row box-aligner" style={{marginTop:"-20px"}}>
<div>
<div className="row" style={{marginLeft:"100px"}}>
{
skills.map((skill)=>(
<div className="col-sm-2" style={{ marginRight:"15px",marginLeft:"0px"}}>
<p className="language row-aligner">{skill}</p>
</div>
))
}
</div>
</div>
<div style={{marginRight:"5px",fontSize:"15px", paddingRight:"30px"}}>
< BsGeoAlt/> New Delhi - 9.6km
</div>
</div>
<div id="designation" className="row" style={{marginTop:"-10px"}}>
<div className="col-md-6">
<h1 className="row-aligner" style={{marginRight:"20px",paddingLeft:"25px",marginLeft:"51px"}}>
<FaTshirt/> 4years,2months
</h1>
</div>
<div className="col-sm-6">
<h2 className="city" style={{paddingLeft:"65px", paddingRight:"20px", fontWeight:"normal",marginLeft:"15px"}}><IoLogoDesignernews/> {' '} Interaction Designer</h2>
</div>
</div>
<div id="salary" className="row" style={{marginTop:"-4px"}}>
<div className="col-md-6" >
<h1 className="row-aligner" style={{marginRight:"-4px", paddingLeft:"25px", marginLeft:"10px"}}><GiTakeMyMoney/> $10k-25k/ mo</h1>
</div>
<div className="col-md-6">
<a href="#" class="btn btn-primary">
Hire Now
</a>
</div>
</div>
</div>
);
};
export default Card;
/Card.jsx/
/*Here is the Parent file. Class component has been used here.*/
import React,{Component} from 'react'
import Card from './CardUI'
class Cards extends Component{
render(){
return(
<div className="container-fluid d-flex justify-content-center" style={{marginTop:"100px"}}>
<div className="row">
<div className="col-md-12">
<Card name={"Sara"}
current_availability={"Available"}
workExperience={"4"}
Location={"delhi"}
distance={"9.6 km"}
JobTitle={"Designer"}
/>
</div>
</div>
</div>
)
}
}
export default Cards;

How to access a function from another component that is located in another js file by clicking a button in create-react-app?

I have two files index.js and map.js. In map.js I have Kartta component, that contains a leaflet map and a method fetchAll() that creates markers on the map from the coordinates that it gets from API, which in this case is test.json. It works fine if I put the method inside componentDidMount(), it creates the markers on load. However I want to create those markers by clicking the button "Haku", which is located inside Sidebar component in index.js.
Here is map.js
import React, { Component } from 'react';
import L from 'leaflet';
import { Map, Marker, Popup, TileLayer } from 'react-leaflet';
import { fetchAll } from './search';
const position = [62.241581, 25.758742];
class Kartta extends Component {
state = {
kohteet: []
}
componentDidMount() {
this.fetchAll();
}
fetchAll = () => {
console.log("täällä");
fetch('test.json')
.then(res => res.json())
.then((data) => {
this.setState({ kohteet: data })
})
.catch(console.log(this.state.kohteet))
}
iconSize = (iconName) => {
if (iconName == 'tree.png') {
return 30, 30
}
else {
return 15, 30
}
}
render() {
return (
<div id="mapid" className="h-100 w-100">
<Map center={position} zoom={7}>
<button onClick={this.haeKaikki}>Hae</button>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
{this.state.kohteet.map((kohde) => (
<Marker key={'key' + kohde.id} position={[kohde.lon, kohde.lat]} icon={
new L.Icon({
iconUrl: require('../img/' + kohde.icon),
iconSize: new L.Point(this.iconSize(kohde.icon)),
id: kohde.id + kohde.icon
})
}>
<Popup>
<h1>{kohde.name}</h1>
<p>{kohde.desc}</p>
</Popup>
</Marker>
))}
</Map>
</div>
)
}
}
export default Kartta
Here is index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './css/main.css';
import 'bootstrap/dist/js/bootstrap.bundle.js';
import 'leaflet/dist/leaflet.css';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faSearch, faInfoCircle } from '#fortawesome/free-solid-svg-icons';
import Kartta from './components/map';
// Yläpalkki
class Navbar extends React.Component {
render() {
return (
<nav id="nav-bar" className="navbar navbar-expand-lg navbar-dark bg-primary">
<a id="nav-bar-a0" className="navbar-brand" href="/">MeijänMetsät</a>
<button id="toggle-search-btn" type="button" href="#sidebar" data-toggle="collapse" className="btn btn-primary">
<FontAwesomeIcon icon={faSearch} />
<span> Haku</span>
</button>
<ul id="nav-bar-ul0" className="navbar-nav mr-auto">
</ul>
<div id="nav-bar-div0" className="dropdown">
<button id="nav-bar-button0" className="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Kirjaudu
<span id="nav-bar-span0" className="caret"></span></button>
<div id="dropdown-div0" className="p-2 dropdown-menu dropdown-menu-right" style={{"minWidth":"350px"}}>
<form id="dropdown-form0">
<div id="dropdown-div1" className="form-group">
<label id="dropdown-label0" htmlFor="exampleInputEmail1">Sähköposti</label>
<input id="dropdown-input0" type="email" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Syötä sähköposti" />
</div>
<div id="dropdown-div2" className="form-group">
<label id="dropdown-label1" htmlFor="exampleInputPassword1">Salasana</label>
<input id="dropdown-input1" type="password" className="form-control" id="exampleInputPassword1" placeholder="Salasana" />
</div>
<div id="dropdown-div3" className="row">
<button id="dropdown-button0" type="submit" className="ml-3 btn btn-primary">Kirjaudu</button>
<button id="dropdown-button2" type="submit" className="ml-2 btn btn-primary">Rekiströidy</button>
<button id="dropdown-button1" type="submit" className="ml-2 btn btn-secondary">Facebook</button>
</div>
</form>
</div>
</div>
</nav>
);
}
}
// Sivupalkki
class Sidebar extends React.Component {
render() {
return (
<div className="p-2 collapse in" id="sidebar">
<div className="list-group panel" id="sidebar-div0">
<form id="sidebar-form0">
<div id="sidebar-div01" className="form-group active">
<label id="sidebar-label0" htmlFor="exampleInputEmail1">Kohteen nimi</label><span> </span>
<FontAwesomeIcon icon={faInfoCircle} className="pointer dropdown-toggle" data-toggle="dropdown" alt="Hakuohjeet" />
<div id="search-info" className="p-2 dropdown-menu dropdown-menu-right">
<p>Hae kirjoittamalla tägejä</p>
</div>
<div className="row">
<div className="col-7 ml-3 p-0">
<input type="text" className="form-control" id="searchByName" aria-describedby="emailHelp" placeholder="Syötä kohteen nimi" />
</div>
<button id="sidebar-button0" type="submit" className="btn btn-primary ml-2 col-3" onClick={() => Kartta.fetchAll}>Haku</button>
</div>
</div>
</form>
<div id="sidebar-div02" className="dropdown">
<a id="sidebar-button1" className="btn btn-light dropdown-toggle p-0 thaku" type="button" data-toggle="dropdown">Tarkennettu haku
<span id="sidebar-span0" className="caret"></span></a>
<div id="sidebar-div020" className="p-0 dropdown-menu border-0 mt-2 w-100 h-100">
<form id="sidebar-form1">
<div id="sidebar-div0200" className="form-group p-0">
<label id="sidebar-label1" htmlFor="exampleInputEmail1">Paikkakunta</label>
<input id="sidebar-input1" type="text" className="form-control" placeholder="Syötä paikkakunta" />
</div>
<div id="ch-div0" className="row pl-3">
<label id="lbl-location">Sijainti</label>
<input id="ch-location" className="mt-2 ml-2" type="checkbox" aria-label="Checkbox for following text input" />
</div>
<div className="input-group mb-3">
<div className="input-group-prepend">
<label className="input-group-text" htmlFor="inputGroupSelect01">Palvelut</label>
</div>
<select className="custom-select" id="inputGroupSelect01">
<option defaultValue>Valitse...</option>
<option value="1">Kakkapaikka</option>
<option value="2">Pissapaikka</option>
<option value="3">Kaljapaikka</option>
</select>
</div>
<div id="dropdown-div3" className="row p-0">
<button id="dropdown-button0" type="submit" className="ml-3 btn btn-primary">Tarkennettu haku</button>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
// Sisältö
class Content extends React.Component {
render() {
return (
<div id="main-container" className="container-fluid h-100 p-0">
<Navbar />
<div id="container0" className="row h-100 w-100 m-0 wrapper">
<Sidebar />
<div id="container02" className="col h-100 w-100 p-0">
<Kartta />
</div>
</div>
</div>
);
}
}
ReactDOM.render(<Content />, document.getElementById('root'));
The button "Haku" has onClick={() => Kartta.fetchAll}, but it does not do anything, it isn't even accessing the fetchAll() function. The function works perfectly if I create the button on the map, but I don't want to do that, the button has to be on the Sidebar as the plan is to use a search word in the future.
Thank you!
you need to create a prop e.g. createmap:booleanin Kartta component. Now in index.js firstly you need to create a state e.g. createmap:boolean (initially set to false) and upon Haku button click you need to set the state:
this.setState({
creatmap:true;
});
you need to include Katta component JSX in index.js render() function e.g.
<Kartta createmap = {this.state.createmap} />
Now in Kartta component on componentDidMount()you can check createmap' prop and based on its value call the functionfetchAll()`:
public componentDidMount() {
if(this.prop.createmap) {
fetchAll();
}
}
what this will do is causing rerendering due to setting state upon button click and will call 'fetchAll()' function if createMap is found true
Hope this helps.
EDIT:
Don't forget to use export keyword with your Kartta component class so you can import it in index.js to create its JSX in render():
export default class Kartta extends Component { ... }
EDIT 2
In your navbar component class initialize state in constructor:
export default class NavBar extends Component {
constructor(props) {
super(props);
this.state: {
createmap: false;
}
}
}
your Kartta component class:
export default class Kartta extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
if(this.props.createmap) {
fetchAll();
}
}

Issues passing data up React tree to change DOM

** This may be a simple answer, I'm new to React, thank you for any help ! **
Back story
I have a modal(bootstrap4) hidden inside the main app with a form inside that, when it rendered, the form is filled out based on the information from the selected recipe (more on that later.)
The recipes are stored locally and with this.state.currentRecipe I know which recipe is being selected (it is used as the index and is set to 0 by default.)
So, using this.state.currentRecipe as the index the first render naturally puts in the first recipe's information.
I attempted to solve this by making a function and passing it down the child components. The recipe-card has all the information and the edit button inside of it. So when the recipe-cards are all rendered by .map() I pass in their index and the function that was passed down in order to change the state of this.state.currentRecipe and re-render the DOM with the form having the new information.
What's wrong
Everything loads however, when I click the edit button the modal pops up with the first recipe always. It will even change this.state.currentRecipe but the DOM doesn't re-render with the proper recipe's information.
How do I get the form's information to update based on which recipe-card I'm in when I click the 'Edit' button?(there is a button in each card).
(and even if it did, would it just hide the modal again?)
Here is the link to the component folder of the repo https://github.com/JeremyWeisener/React-Recipe-box/tree/master/src/components
in case the code below isn't enough information
Here is the inside of the 4 main files I believe matter (cleaned up a bit and put here to make life easier)
app.js
import React, { Component } from 'react';
import RecipeCard from './recipe-card';
import RecipeBook from './recipe-book';
import AddRecipe from './add-recipe';
import RecipeEditer from './edit-recipe';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
currentRecipe: 0,
recipes: JSON.parse(localStorage.getItem('cookBook')),
updateKey: 0,
counter: 0
}
}
changeRecipe = (arg) => {
this.setState({currentRecipe:arg});
}
render() {
return (
<div>
<div>
<RecipeBook changeRecipe={this.changeRecipe.bind(this)} recipes={this.state.recipes} />
</div>
<div id="popUps">
<AddRecipe />
<RecipeEditer index={this.state.currentRecipe} forglory={this.state} />
</div>
<div id="editPopup">
</div>
</div>
);
}
}
recipe-book.js
import React from 'react';
import RecipeCard from './recipe-card';
const RecipeBook = (props) => {
var changeRecipe = props.changeRecipe;
console.log(props);
const DisplayRecipes = props.recipes.map((recipe, index) => {
return <RecipeCard index={index} key={index+1} recipe={recipe} changeRecipe={changeRecipe.bind(this)} />
})
return (
<div id="accordion" role="tablist" aria-multiselectable="true">
{DisplayRecipes}
<div>
<button className="btn btn-primary" type="button" data-toggle="modal" data-target="#addRecipe"> Add Recipe </button>
</div>
</div>
);
}
export default RecipeBook;
recipe-card.js
import React from 'react';
import Ingredients from './recipe-ingredients';
import Steps from './recipe-steps';
import RecipeEditer from './edit-recipe';
const RecipeCard = (props) => {
const changeRecipe = props.changeRecipe;
return (
<div>
{/*Card Start*/}
<div className="recipe card">
{/*Header*/}
<div className="card-header" role="tab" id={`heading${props.index}`}>
<h5 className="mb-0">
<a data-toggle="collapse" data-parent="#accordion" href={`#collapse${props.index}`} aria-expanded="true" aria-controls={`collapse${props.index}`}>
{props.recipe.title}
</a>
</h5>
</div>
{/*End Header*/}
{/*Collapse Div*/}
<div id={`collapse${props.index}`} className="collapse" role="tabpanel" aria-labelledby={`heading${props.index}`}>
{/*Card IMG*/}
<img className="card-img-top" src="./img/Fried Chik'n-edit1.jpg" />
{/*Card Block*/}
<div className="card-block">
<p className="card-text">
</p>
{/* Ingredients */}
<h3>Ingredients</h3>
<Ingredients parts={props.recipe.ingredients} />
{/* Steps */}
<h3>Steps</h3>
<Steps levels={props.recipe.steps} />
Print Recipe
{/*Edit Button is here*/}
<button onClick={() => {changeRecipe(props.index)}} className="btn btn-success" type="button" data-toggle="modal" data-target="#editRecipe"> Edit Recipe </button>
{/*Edit Button is here*/}
Delete Recipe
</div>
{/*End Card Block*/}
</div>
{/*End Collapsable*/}
</div>
{/*End Card*/}
</div>
);
}
export default RecipeCard;
edit-recipe.js
import React from 'react';
const RecipeEditer = (props) => {
var index = props.index;
var cookBook = JSON.parse(localStorage.getItem("cookBook"));
var editMe = cookBook[props.forglory.currentRecipe];
const UpdateRecipe = () => {
var formData = $('#recipeEditer').serializeArray();
var newRecipe = {};
newRecipe.title = formData[0]['value'];
newRecipe.image = formData[1]['value'];
newRecipe.ingredients = formData[2]['value'].split(',');
newRecipe.steps = formData[3]['value'].split(',');
cookBook[index] = newRecipe;
localStorage.setItem("cookBook", JSON.stringify(cookBook));
}
return (
<div className="modal fade" id="editRecipe" tabIndex="-1" role="dialog" aria-labelledby="editRecipeLabel" aria-hidden="false">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
{/* Title */}
<h5 className="modal-title" id="exampleModalLabel">
Edit Recipe
</h5>
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="false">×</span>
</button>
</div>
<div className="modal-body">
<form id="recipeEditer" name="editRecipe">
<label htmlFor="name"><h4>Name</h4></label>
<input id="name" className="form-control" name="title" type="text" defaultValue={editMe.title} />
<label htmlFor="image"><h4>Image</h4></label>
<input id="image" className="form-control" name="image" type="text" defaultValue={editMe.image} />
<label htmlFor="ingredients"><h4>Ingredients</h4></label>
<textarea id="ingredients" className="form-control" name="ingredients" rows="4" cols="48" defaultValue={editMe.ingredients}></textarea>
<label htmlFor="steps"><h4>Steps</h4></label><br/>
<textarea id="steps" className="form-control" name="steps" cols="48" rows="4" defaultValue={editMe.steps} ></textarea>
</form>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" data-dismiss="modal">Close</button>
{/*Submit Button*/}
<button onClick={UpdateRecipe} type="button" className="btn btn-success" data-dismiss="modal">Change Recipe</button>
{/*Submit Button*/}
</div>
</div>
</div>
</div>
);
}
export default RecipeEditer;
thank you very much if you even glanced, if there is any more information that can help please don't hesitate to ask !
You are binding changeRecipe to this in recipe-book.js, thus setting its context to RecipeBook.
Try changing
<RecipeCard index={index} key={index+1} recipe={recipe} changeRecipe={changeRecipe.bind(this)} />
to
<RecipeCard index={index} key={index+1} recipe={recipe} changeRecipe={changeRecipe} />
You may not even have to use bind in app.js, since changeRecipe is defined as an arrow function.

How do I add the bible.org widget to my site?

I hope everyone is having a good day.
I am working with the bible.org API to create a learning app for the bible.
bible.org gives the option to input their widget on your own website.
When you finish creating your widgets they give you this:
Paste the following code into your website or blog.
BIBLESEARCH.widget({
"background": "FFFFFF",
"color": "E2615C"
});
I am using Reactjs and would like to implement it in my Header component.
I provided an example of my H
import React from 'react';
import {startNewBookAction} from '../Actions/index';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {Link} from 'react-router-dom';
import axios from 'axios';
import {bibleBooks} from '../../data/bibleBooks';
class Header extends React.Component {
constructor(props) {
super(props);
this.state = {
book:"Genesis"
};
}//end of constructor
handleNewBook() {
let userBook = this.state.book;
console.log('The book chosen by the user', this);
this.props.startNewBookAction(userBook)
}//handleNewBook
handleLogout() {
console.log('loging out..');
axios.delete('/login').then(res => {
console.log('back from the server with', res);
window.location = "/?#/user";
})
}//end of handleLogout
showBibleBooks() {
//displays the option tag for every book in the bible
console.log('showing the books');
let books = bibleBooks;
return(
books.map((b, id) => {
return (
<option value={b} key={id}>{b}</option>
);
})
);//end of return
}//end og showBibleBooks
start() {
console.log('start', this)
}//end of start
render() {
return (
<div id="UserHeader">
<header className="main-header">
<div className="logo"><a href="index.html" >BBS</a></div>
<div className="navbar navbar-static-top">
<div className="btn-grps pull-right">
<a className="pink-btn dark-btn" onClick={this.handleLogout.bind(this)} >Logout</a>
<a className="pink-btn" data-toggle="modal" data-target="#myModal">New Book</a>
</div>
</div>
</header>
<div className="col-md-4 ">
<div id="myModal" className="modal fade" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">×</button>
<form onSubmit={this.handleNewBook.bind(this)}>
<h4 className="modal-title" >New Book</h4>
<label htmlFor="book">Book:</label>
<select name="book" id="" onChange={event => this.setState({book:event.target.value})}>
{this.showBibleBooks()}
</select>
<input type="button" value="Start0" onClick={this.start.bind(this)}/>
</form>
</div>
<div className="modal-body">
</div>
<div className="modal-footer">
<button type="button" className='btn btn-success' data-dismiss="modal" id="signupSubmit" onClick={this.handleNewBook.bind(this)}> Enter</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}//end of render
}//end of classNameName
function mapDispatchToProps(dispatch) {
return bindActionCreators({
startNewBookAction
},
dispatch)
}
function mapStateToProps(state) {
return {
newBook:state
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Header);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
eader component. How can I implement this widget in my app.
Try to add after constructor:
componentWillMount () {
const script = document.createElement("script");
script.src = "//bibles.org/widget/client";
script.async = true;
document.body.appendChild(script);
}

React - Open Modal Dialog (Bootstrap)

First, I'm almost new to reactjs. I want to create a simple editing mask for getting deeper into reactjs.
What is the "Best Practice" for this situation?
I'm having a page, where you can simply add, change or delete a company entry.
What I want to achieve is, to open a modal dialog window, when I click on a company entry. In the modal dialog window then, the user can modify or delete the entry.
First I created a CompanyList component.
import React, { Component } from 'react';
import Company from './Company';
class CompanyList extends Component {
constructor(props) {
super(props);
this.state = {
search: '',
companies: props.companies
};
}
updateSearch(event) {
this.setState({ search: event.target.value.substr(0,20) })
}
addCompany(event) {
event.preventDefault();
let nummer = this.refs.nummer.value;
let bezeichnung = this.refs.bezeichnung.value;
let id = Math.floor((Math.random()*100) + 1);
$.ajax({
type: "POST",
context:this,
dataType: "json",
async: true,
url: "../data/post/json/companies",
data: ({
_token : window.Laravel.csrfToken,
nummer: nummer,
bezeichnung : bezeichnung,
}),
success: function (data) {
id = data.Nummer;
this.setState({
companies: this.state.companies.concat({id, nummer, bezeichnung})
})
this.refs.bezeichnung.value = '';
this.refs.nummer.value = '';
}
});
}
render() {
let filteredCompanies = this.state.companies.filter(
(company) => {
return company.bezeichnung.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
return (
<div>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">Search</div>
<div className="col-xs-12 col-sm-12 col-md-9 col-lg-9">
<div className="form-group">
<input className="form-control" type="text" value={this.state.search} placeholder="Search" onChange={this.updateSearch.bind(this)} />
</div>
</div>
</div>
<form onSubmit={this.addCompany.bind(this)}>
<div className="row">
<div className="col-xs-12 col-sm-12 col-md-12 col-lg-12">Create new entry</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<input className="form-control" type="text" ref="nummer" placeholder="New company no." required />
</div>
</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<input className="form-control" type="text" ref="bezeichnung" placeholder="New company name" required />
</div>
</div>
<div className="col-xs-12 col-sm-12 col-md-3 col-lg-3">
<div className="form-group">
<button type="submit" className="btn btn-default">Add new company</button>
</div>
</div>
</div>
</form>
<div className="row">
<div className="col-xs-10 col-sm-10 col-md-10 col-lg-10">
<ul>
{
filteredCompanies.map((company)=> {
return (
<div>
<Company company={company} key={company.id} />
</div>
);
})
}
</ul>
</div>
</div>
</div>
);
}
}
export default CompanyList
The Company component looks like this:
import React, { Component } from 'react';
class Company extends Component {
constructor(props) {
super(props);
this.state = {
company: props.company,
onClick: props.onClick
};
}
render() {
return (
<div>
<li>
<div className="cursorPointer" >
{this.props.company.nummer} {this.props.company.bezeichnung}
</div>
</li>
</div>
);
}
}
export default Company
My issue is now, how and where to implement the modal dialog?
Is it best practice to create an own component for it e.g. CompanyOptions? Should it be part of Company or better one component added in CompanyList? But then, how to pass the current Company to the modal dialog.
Sorry, if I'm asking too many questions. But I want to find out how it is recommended in reactjs.
UPDATE
Now I've created an own component for it.
This component looks like this:
import React, { Component } from 'react';
class CompanyOptions extends Component {
constructor(props) {
super(props);
this.state = {
company: props.company,
css: props.css,
onClick: props.onClick
};
}
render() {
return (
<div>
<div className={this.state.css} tabindex="-1" role="dialog">
<div className="modal-dialog" role="document">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 className="modal-title">Company entry "{this.state.company.bezeichnung}"</h4>
</div>
<div className="modal-body">
<p>One fine body…</p>
</div>
<div className="modal-footer">
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" className="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default CompanyOptions
In the Company component I render it this way:
render() {
return (
<div>
<li>
<div className="cursorPointer" onClick={this.toggleOptionFields.bind(this)}>
{this.props.company.nummer} {this.props.company.bezeichnung}
</div>
<CompanyOptions company={this.state.currentCompany} css={this.state.optionFieldsCss} />
...
I've created a state and a method for the click event:
constructor(props) {
super(props);
this.state = {
company: props.company,
onClick: props.onClick,
editFieldsCss: "displayNone",
optionFieldsCss: "modal fade",
currentCompany: props.company,
};
}
and the method:
toggleOptionFields() {
var css = (this.state.optionFieldsCss === "modal fade in displayBlock") ? "modal fade" : "modal fade in displayBlock";
this.setState({
"optionFieldsCss":css,
currentCompany: this.company
});
}
But when I click on the company the css in the component call is updated. But not in the component itself:
Why? Anybody an idea?
The best way is to create a new component for a modal. This way it would be reusable.
Then you can include it where you need it and you can send all company info via props to that modal.
Add an state property showModal and set it to false. Then onClick event change showModal to true. Then in your render method you can check if(this.state.showModal) and then show modal.
Your state :
constructor(props){
super(props);
this.state = {
showModal: false,
currentCompanyName: "",
currentCompanyNumber: ""
}
}
Then onClick event:
handleClick(currentCompanyName, currentCompanyNumber){
this.setState({
showModal: true,
currentCompanyName: currentCompanyName,
currentCompanyNumber: currentCompanyNumber
})
}
And then in your render:
render(){
if(this.state.showModal)
return <MyModal companyName={this.state.currentCompanyName} companyNumber={this.state.currentCompanyNumber} />
return (
//Rest of the code
)
}

Categories

Resources