My dropdown Menu does not working (react.js) - javascript

I need help with this code, at the end production process on the page called projects, my dropdown menu does not work and I have tried many ways to fix that, nevertheless, I can't fix that. Please I am looking forward to your help and answer.
I'm using React-Bootstrap v1.4.3 (Bootstrap 4.6)
import React, { Component } from 'react';
import Project from '../components/project.js';
import { projectData } from '../projectData';
import './projects.css';
export default class Projects extends Component {
constructor(props) {
super(props);
this.state = {
projectID: '',
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
const projectID = e.target;
this.setState({ projectID: projectID })
}
render() {
const selectedProject = this.state.projectID;
return(
<div className="col-xs-12 col-lg-10 offset-lg-1 col-xl-8 offset-xl-2 mb-5 pb-5">
<div className="row justify-content-center pb-4">
<div class="dropdown">
<button
class="btn btn-retro dropdown-toggle textspaced textlarge"
type="button"
id="dropdownMenuButton"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Mission Select
</button>
<div class="dropdown-menu raleway text-center" aria-labelledby="dropdownMenuButton">
{projectData.map((project, index) => {
return <button class="dropdown-item" onClick={this.handleClick} id={index}>{project.title}</button>
})}
</div>
</div>
</div>
<div className="pagebox shadow-lg row justify-content-center pr-0 pl-0">
{this.state.projectID
? <Project
title={projectData[selectedProject].title}
image={projectData[selectedProject].image}
description={projectData[selectedProject].description}
technologies={projectData[selectedProject].technologies}
link={projectData[selectedProject].link}
date={projectData[selectedProject].date_created}
github={projectData[selectedProject].github}
/>
: <h2 className="col-12 text-center textyellow textspaced pt-5 mt-5">
Please select a mission above.
</h2>
}
</div>
</div>
)
}
}

Related

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

passing index through react components

I'm studying Reactjs and I'm building a tasks project (CRUD) but I'm stuck at the point of editing, the editing part is in another component and I'm not able to send the index of the task that will be edit, I read the documentation but I'm not capable to make it, please if someone can see my code and tell what I'm doing wrong.
the app (main)code
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
// data
import { todos2 } from './todos.json';
// subcomponents
import TodoForm from './components/TodoForm';
import TodoFormEdit from './components/TodoFormEdit';
class App extends Component {
constructor() {
super();
this.state = {
todos2, mode:'view'
}
this.handleAddTodo = this.handleAddTodo.bind(this);
this.handleEdit2 = this.handleEdit2.bind(this);
}
removeTodo(index) {
this.setState({
todos2: this.state.todos2.filter((e, i) => {
return i !== index
})
});
}
handleAddTodo(todo) {
this.setState({
todos2: [...this.state.todos2, todo]
})
}
handleEdit2(i) {
this.setState({mode: 'edit'});
//const mode = mode === 'edit';
alert(i);
/* alert(this.state.todos2[i].title);
alert(this.state.todos2[i].priority);
alert(this.state.todos2[i].description);
alert(this.state.todos2[i].language);*/
}
render() {
const todosAll = this.state.todos2.map((todo, i) => {
return (
<div className="col-md-4" key={i}>
<div className="card mt-4">
<div className="card-title text-center">
<h3>{todo.title} - { i } </h3>
<span className="badge badge-pill badge-danger ml-2">
{todo.priority}
</span>
</div>
<div className="card-body">
<div>
{todo.description}
</div>
<div>
{todo.language}
</div>
</div>
<div className="card-footer">
<button
className="btn btn-danger"
onClick={this.removeTodo.bind(this, i)}>
Delete
</button>
<button
className="btn btn-warning ml-2"
onClick={this.handleEdit2.bind(this, i)}>
Edit
</button>
</div>
</div>
</div>
)
});
return (
<div className="App">
<nav className="navbar navbar-dark bg-dark">
<a className="navbar-brand" href="/">
Tasks
<span className="badge badge-pill badge-light ml-2">
{this.state.todos2.length}
</span>
</a>
</nav>
<div className="container">
<div className="row mt-4">
<div className="col-md-4 text-center">
<img src={logo} className="App-logo" alt="logo" />
{/* <TodoForm onAddTodo={this.handleAddTodo} ></TodoForm> */ }
{this.state.mode === 'view' ? (
<TodoForm onAddTodo={this.handleAddTodo} />
) : (
<TodoFormEdit index={this.state.i}/>
)}
</div>
<div className="col-md-8">
<div className="row">
{todosAll}
</div>
</div>
</div>
</div>
</div>
)
}
}
export default App;
and the Edit component:
import React, { Component } from 'react';
// data
import { todos2 } from '../todos.json';
class TodoFormEdit extends Component {
constructor (i) {
super(i);
this.state = {
todos2
};
}
render() {
return (
<div>
{this.state.todos2[0].title}
</div>
)
}
}
export default TodoFormEdit;
You're passing this.state.i:
<TodoFormEdit index={this.state.i}/>
It's not clear where you set it–I see mode and todos2 state properties, I don't see i anywhere.

How to sort data and display it in reactjs?

I want to display projects in sorted manner when user clicks on sort by funds then it should display the projects in sorted by funds but my code is not working why so ? I am importing the sortBy() function and using it when user clicks on the button.
home.js:
import React, { Component } from 'react';
import Card from '../common/card';
import Projects from '../../data/projects';
import { sortBy } from './helper';
export default class Home extends Component {
constructor(props) {
super(props);
this.state = {
projects: Projects
}
}
render() {
return (
<div>
<div className="header">
<div className="buttonContainer">
<div>
<button className="btn btn-primary mycustom dropdown-toggle mr-4" type="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">Sort by </button>
<div className="dropdown-menu">
<a className="dropdown-item" href="#" onClick={() => sortBy('funded')}>Percentage fund</a>
<a className="dropdown-item" href="#" onClick={() => sortBy('backers')}>Number of backers</a>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
{this.state.projects.map( (val,index) => (
<div class="col-3">
<Card title={val.title} by={val.by} blurb={val.blurb}
url={val.url} funded={val.funded} backers={val.backers} imgurl={index}/>
</div>
))}
</div>
</div>
</div>
)
}
}
helper.js:
import projects from '../../data/projects';
export function sortBy (searchTerm) {
if(searchTerm === 'funded'){
return projects.sort((a,b) => a.funded - b.funded);
}else if(searchTerm === 'backers'){
return projects.sort((a,b) => a.backers - b.backers);
}
}
projects.js:
http://jsfiddle.net/0z8xcf1o/
In your render function, you should iterate over this.state.projects instead of Projects
You need to update your state on every sort
Your sortBy function can be simplified, it should set the state for you, and it would be better to add it to the component:
-
sortBy(searchTerm) {
this.setState({ projects: [...Projects].sort((a, b) => a[searchTerm] - b[searchTerm]) });
}
and then call it with
onClick={() => this.sortBy('funded')}

Pass in states as props to another component in iteration

I have two components: CardContainer and SingleVideoContainer.
CardContainer will contain multiple SingleVideoContainers based on the data in the database.
import React, { Component } from 'react';
import Modal from 'boron/WaveModal';
//Default firebase App
import * as firebase from 'firebase';
import { firebaseApp } from '../firebase/firebase';
import SingleCardContainer from '../cards/SingleCardContainer';
var dataRef = firebaseApp.database();
var dataArray = [];
class CardContainer extends Component {
constructor(props) {
super(props);
this.state = {
userid: "",
videoLink: "",
likes: "",
challenges: "",
videoCat: "",
videoDesc: "",
videoTitle: "",
profilePic: "",
disikes: ""
}
this.showModal = this.showModal.bind(this);
this.hideModal = this.hideModal.bind(this);
this.componentDidMount = this.componentDidMount.bind(this);
}
showModal() {
this.refs.modal.show();
}
hideModal() {
this.refs.modal.hide();
}
componentDidMount() {
}
render() {
function initApp() {
var videosRef = dataRef.ref('posts/');
videosRef.on('value', function (snapshot) {
snapshot.forEach(function (data) {
var userInfo = {};
var userArray = [];
//Set up the next user array group
//9 items for 1 user.
userInfo.userid = data.val().userid;
userInfo.likes = data.val().likes;
userInfo.dislikes = data.val().dislikes;
userInfo.challenges = data.val().challenges;
userInfo.profilePic = data.val().profilePic;
userInfo.videoCategory = data.val().videoCategory;
userInfo.videoDesc = data.val().videoDesc;
userInfo.videoTitle = data.val().videoTitle;
userInfo.videoURL = data.val().videoURL;
//Then save the object in the array
userArray.push(userInfo);
//change the index to next user.
})
});
}
/**
* This loads when the page loads (right before renders)
*/
window.addEventListener('load', function () {
initApp()
});
return (
<div id="bodyType">
{
userArray.map(
data => <SingleCardContainer
userid={data.userid}
title={data.title}
likes={data.likes}
dislikes={data.challenges}
videoURL={data.videoURL}
/>)
}
</div>
)
}
}
export default CardContainer;
I want to render the SingleCardContainer by passing in the information from the dataArray as props. Each user has 9 items that I need to pass in as props.
How would I do that? I can render 1 but not multiple ones.
Here is the SingleCardContainer:
import React, { Component } from 'react';
import {
Player, ControlBar,
ForwardControl, CurrentTimeDisplay,
TimeDivider, VolumeMenuButton, BigPlayButton
} from 'video-react';
import ModalContainer from '../cards/ModalContainer';
class SingleCardContainer extends Component {
constructor(props) {
super(props);
this.likeButton = this.likeButton.bind(this);
this.challengeButton = this.challengeButton.bind(this);
this.dislikeButton = this.dislikeButton.bind(this);
}
likeButton() {
}
challengeButton() {
}
dislikeButton() {
}
//We will have to pass down the states from CardContainer as props to this so that they get updated in real-time *fingers-crossed*
render() {
return (
<div className="container">
<div className="card" id="generalCard">
<div className="card-text">
<div id="singleVideoContainer">
<h3>{this.props.title}</h3><p> {this.props.userid}</p>
<Player poster="" src={this.props.videoURL}></Player>
<div id="videoInfoSection">
<div className="row" id="buttonContainerRow">
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={() => this.likeButton()} role="button" href="#"><i className="fa fa-thumbs-up"></i></a>
<p>{this.props.likes}</p>
</div>
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={() => this.challengeButton()} role="button" href="#"><i className="fa fa-shield"></i></a>
<p>{this.props.challenges}</p>
</div>
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={() => this.dislikeButton()} role="button" href="#"><i className="fa fa-thumbs-down"></i></a>
<p>{this.props.dislikes}</p>
</div>
</div>
<div id="commentSection">
<p>{this.props.videoDesc}</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default SingleCardContainer;
You should put any data calls into componentDidMount and never in render. Also note that you can simply use map to convert the snapshot array to the values. Then call setState which will eventually call render with the new data.
import React from 'react';
import * as firebase from 'firebase';
import { firebaseApp } from '../firebase/firebase';
class CardContainer extends React.Component {
constructor(props) {
super(props);
this.state = { data: [] };
}
componentDidMount() {
var dataRef = firebaseApp.database();
var videosRef = dataRef.ref('posts/');
videosRef.on('value', (snapshot) => {
var data = snapshot.map(o => o.val());
this.setState({ data: data });
});
}
render() {
const { data } = this.state;
return (<div>
{data.map(o => <SingleCardContainer {...o} />)}
</div>);
}
}
class SingleCardContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
const {title, userid, videoURL, videoDesc, likes, dislikes, challenges} = this.props;
return (
<div className="container">
<div className="card" id="generalCard">
<div className="card-text">
<div id="singleVideoContainer">
<h3>{title}</h3>
<p>{userid}</p>
<p>{videoURL}</p>
<div id="videoInfoSection">
<div className="row" id="buttonContainerRow">
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={console.log} role="button" href="#"><i className="fa fa-thumbs-up"></i></a>
<p>{likes}</p>
</div>
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={console.log} role="button" href="#"><i className="fa fa-shield"></i></a>
<p>{challenges}</p>
</div>
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={console.log} role="button" href="#"><i className="fa fa-thumbs-down"></i></a>
<p>{dislikes}</p>
</div>
</div>
<div id="commentSection">
<p>{videoDesc}</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
Below I have a working code snippet where I stripped out Firebase and replaced it with hard-coded data to prove that this will work with React.
class CardContainer extends React.Component {
constructor(props) {
super(props);
this.state = { data: [] };
}
componentDidMount() {
const data = [
{title: 'Title1', userid:'u1', videoURL:'video1.webm', videoDesc:'desc1', likes: 'like1', dislikes: 'dislike1', challenges: 'challenge1'},
{title: 'Title2', userid:'u2', videoURL:'video2.webm', videoDesc:'desc2', likes: 'like2', dislikes: 'dislike2', challenges: 'challenge2'},
{title: 'Title3', userid:'u3', videoURL:'video3.webm', videoDesc:'desc3', likes: 'like3', dislikes: 'dislike3', challenges: 'challenge3'},
];
this.setState({ data: data });
}
render() {
const { data } = this.state;
return (<div>
{data.map(o => <SingleCardContainer {...o} />)}
</div>);
}
}
class SingleCardContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
const {title, userid, videoURL, videoDesc, likes, dislikes, challenges} = this.props;
return (
<div className="container">
<div className="card" id="generalCard">
<div className="card-text">
<div id="singleVideoContainer">
<h3>{title}</h3>
<p>{userid}</p>
<p>{videoURL}</p>
<div id="videoInfoSection">
<div className="row" id="buttonContainerRow">
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={console.log} role="button" href="#"><i className="fa fa-thumbs-up"></i></a>
<p>{likes}</p>
</div>
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={console.log} role="button" href="#"><i className="fa fa-shield"></i></a>
<p>{challenges}</p>
</div>
<div className="col-md-4 col-xs-6 col-sm-4">
<a className="supportButtons" onClick={console.log} role="button" href="#"><i className="fa fa-thumbs-down"></i></a>
<p>{dislikes}</p>
</div>
</div>
<div id="commentSection">
<p>{videoDesc}</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
ReactDOM.render(<CardContainer />, document.querySelector('div'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<div><!--REACT ROOT--></div>
However, I am not as familiar with Firebase so any bugs you run into would be due to the data coming from Firebase which I don't have control over and might require a different question.

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