Toggle element isHidden True/False with React - javascript

I have a problem with this code, my Toggle button doesn't display the Child element but gives me a full blank page
Here is the code
class App extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {items: [] , isHidden: true};
this.toggleHidden = this.toggleHidden.bind(this);
}
componentDidMount() {
fetch("/customers")
.then(result=>result.json())
.then(items=>this.setState({items}));
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
});
}
render() {
return (
<div id='customerDetails'>
{this.state.items.map(item=><customerDetail>
<div id={item._id} >
<button onClick={this.toggleHidden} data-arg1={item._id} value='U'/>
{item.cost}
{!this.state.isHidden && <Child >
<div className='modal'>
<form onSubmit={this._handleUpdate}>
<input type='text' id='cost' name='cost'/>
<input type='hidden' id="_id" name='_id' value=item.id />
<input type='submit' value='Update'/>
</form>
</div>
</Child>
}
</div>
</customerDetail>)}
</div>
);
}
}
Any idea , i do not know if it's coming from the fact all that happens in an iteration
I also tried this standalone source code from StackOverflow React toggle component that should work, and it does not work....blank page
Any idea
Thanks

Firstly you need fix errors in the code.
Change line <input type='hidden' id="_id" name='_id' value=item.id /> to <input type='hidden' id="_id" name='_id' value={item.id} />

i just tried this in my parent component render function:
<button onClick={this.toggleHidden} value='U'/>
{item.cost}
{!this.state.isHidden && <Child />}
and on the bottom of the code i add a Child class:
class Child extends React.Component {
render() {
return (
<div className='modal'>
<form >
<input type='text' id='cost' name='cost'/>
<input type='hidden' id="_id" name='_id' />
<input type='submit' value='Update'/>
</form>
</div>
)
}
}
But i have stil a blank page when toggle

I made my code work, here it is :
Remove Child component at the bottom of the page
Add a function CHild at the beginning :
function Child(props) {
return (
<div className='modal'>
<form onSubmit={props.onClick}>
<input type='text' id='cost' name='cost'/>
<input type='hidden' id="_id" name='_id' value={props.value} />
<input type='submit' value='Update'/>
</form>
</div>
);
}
Added the function renderChild in my parent component :
renderChild(i) {
return (
<Child
value={i}
onClick={() => this.props.onClick(i)}
/>
);
}
Finally in the render of my parent component , replace the line :
{!this.state.isHidden && <Child/>}
by
{!this.state.isHidden && this.renderChild(item._id)}
Now my toggle function works

Related

How to call a function in a function based ReactJS component?

In ReactJS would like to have a component from a function, and send a call to a function when a form is posted.
This example doesn't work. How can be fixed?
import React from 'react';
import Link from "react-router-dom/Link";
function AddPhoto(props) {
return (<div>
<h1>Pickture</h1>
<Link className='cancelIcon' to="/"> </Link>
<div>
<form className="form" onSubmit={e => this.handleSubmit(e)}>
<input className='.form input' type='text' placeholder='Link' name='link'/>
<input className='.form input' type='text' placeholder='Description' name='description'/>
<button> post</button>
</form>
</div>
</div>)
}
export function handleSubmit(event) {
console.log("Form has been submitted");
console.log(event.target.element.link.value);
}
I think there are several issues with your code.
You probably want to export your AddPhoto component instead of your handleSubmit function. Assuming that your file is only exporting your AddPhoto component, you don't have to declare a constant and you can straightaway export default your AddPhoto function.
I actually don't see the reason to export your handleSubmit function. So I will include that function inside your AddPhoto component.
There is a - in your this.handleSubmit function, also functional component don't have to use this, furthermore your handleSubmit function is not within your functional component's scope. So it won't work.
You probably don't need the . in your input className props as well.
I've formatted your code to make it look cleaner :)
Here are the codes for you to refer.
const AddPhoto = (props) => {
const handleSubmit = (event) => {
// Add this if you want to prevent the page from reloading and updating your url
event.preventDefault();
console.log("Form has been submitted");
// Assuming you want to get the `link` field's value, you can get it by using this
console.log(event.target.link.value);
}
return (
<div>
<h1>Pickture</h1>
<Link className="cancelIcon" to="/">
{" "}
</Link>
<div>
<form className="form" onSubmit={handleSubmit}>
<input
className="form input"
type="text"
placeholder="Link"
name="link"
/>
<input
className="form input"
type="text"
placeholder="Description"
name="description"
/>
<button type="submit">post</button>
</form>
</div>
</div>
);
}
export default AddPhoto;
Remove this from your handleSubmit since it's declared outside.
Remove export if you're declaring the function in the same file. Otherwise, you would have to define your function in a separate file and then import from there.
function AddPhoto(props) {
return (<div>
<h1>Pickture</h1>
<Link className='cancelIcon' to="/"> </Link>
<div>
{/* Removed this.*/}
<form className="form" onSubmit={e => handleSubmit(e)}>
<input className='.form input' type='text' placeholder='Link' name='link'/>
<input className='.form input' type='text' placeholder='Description' name='description'/>
<button> post</button>
</form>
</div>
</div>)
}
// Removed export
function handleSubmit(event) {
console.log("Form has been submitted");
console.log(event.target.element.link.value);
}
There are quite some issue with your code:
The button doesn’t have a type=“submit” on it, so therefor it won’t even submit the form when pressed.
HandleSubmit is an function specific to AddPhoto, so it should be inside the AddPhoto component. (I also like to use an arrow function in this case because it should be an anonymous function).
There is no need the use this because first of all this keyword is only used in classes to bind functions to the class. So because AddPhoto is an functional component, you don’t have to bind the function to the class.
You should add event.preventDefault();, because otherwise the page will reload (to submit the form) and you will lose your state of your application.
import React from 'react';
import Link from 'react-router-dom/Link';
export default function AddPhoto() {
const handleSubmit = event => {
event.preventDefault();
const link = event.target.link;
const description = event.target.description;
console.log('Form has been submitted');
};
return (
<div>
<h1>Picture</h1>
<Link className="cancelIcon" to="/">
cancel
</Link>
<div>
<form className="form" onSubmit={handleSubmit}>
<input
className="form-input"
type="text"
placeholder="Link"
name="link"
ref={linkInput}
/>
<input
className="form-input"
type="text"
placeholder="Description"
name="description"
ref={descriptionInput}
/>
<button type="submit">post</button>
</form>
</div>
</div>
);
}
Try this:
import React from 'react';
import Link from "react-router-dom/Link";
export function AddPhoto(props) {
return (<div>
<h1>Pickture</h1>
<Link className='cancelIcon' to="/"> </Link>
<div>
<form className="form" onSubmit={handleSubmit}>
<input className='.form input' type='text' placeholder='Link' name='link'/>
<input className='.form input' type='text' placeholder='Description' name='description'/>
<button> post</button>
</form>
</div>
</div>)
}
function handleSubmit(event) {
console.log("Form has been submitted");
console.log(event.target.element.link.value);
}
I think you should be needing to write something like ...
import React from 'react';
import Link from "react-router-dom/Link";
export const AddPhoto = props => {
const handleSubmit = e =>{
return(
console.log("Form has been submitted");
console.log(e.target.element.link.value);
)
}
return (<div>
<h1>Pickture</h1>
<Link className='cancelIcon' to="/"> </Link>
<div>
<form className="form" onSubmit={e => handleSubmit(e)}>
<input className='.form input' type='text' placeholder='Link' name='link'/>
<input className='.form input' type='text' placeholder='Description' name='description'/>
<button> post</button>
</form>
</div>
</div>)
}
AddPhoto.defaultProps = {
onSubmit: ()=>{}
}

Select List not working in ReactJS

I am facing a problem with the select list the onChange event is not being triggered. I can't set the value selected from the select list in this.state variable. Any help will be appreciated.
class SelectActivity extends React.Component{
render(){
return (
<select value={this.props.value} onChange={() =>{this.props.onSelect()}}> {this.props.items.map((item,index) =>{
return <option value={index}>{item}</option>})}
</select>
)
}
}
class Form extends React.Component{
constructor(props){
super(props)
this.state = {first:"",last:"",activity:0,restriction:{a:false,b:false,c:false}}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event){
this.setState({[event.target.name]:event.target.value},()=>{console.log(this.state)})
}
handleCheck(key) {
return function (event) {
var restriction = Object.assign({},this.state.restriction);
restriction[key] = event.target.checked;
this.setState({restriction:restriction},()=>{console.log(this.state)});
}.bind(this);
}
render(){
return(
<form>
<div>
First Name<input name="first" value={this.state.first} onChange={this.handleChange}/>
</div>
<div>
Last Name<input name="last" value={this.state.last} onChange={this.handleChange}/>
</div>
<div>
<input type="checkbox" checked={this.state.restriction.a} onChange={this.handleCheck("a")}/>
<label>a) Dietarty Restriction</label>
</div>
<div>
<input type="checkbox" checked={this.state.restriction.b} onChange={this.handleCheck("b")}/>
<label>b) Physical Disablities</label>
</div>
<div>
<input type="checkbox" checked={this.state.restriction.c} onChange={this.handleCheck("c")}/>
<label>c) Medical Needs</label>
</div>
<div>
<SelectActivity name="activity" items={["Science Lab","Swimming","Painting","Cooking"]} value={this.state.activity} onSelect={this.handleChange}/>
</div>
</form>
)
}
}
ReactDOM.render(
<Form/>,
document.getElementById("root")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id="root"></div>
You are not sending the event that is triggered on change of your select input, but you are just calling the function with
onChange={ () => {this.props.onSelect()} }
Also, you didn't have any name assigned to your select input.
Please update your select input to:
<select
value={this.props.value}
name={this.props.name}
onChange={this.props.onSelect} // assigning the function, so it can be trigged with all argument
>
{
this.props.items.map((item,index) => {
return <option value={index}>{item}</option>
})
}
</select>
class SelectActivity extends React.Component{
render(){
return (
<select value={this.props.value} name={this.props.name} onChange={this.props.onSelect}> {this.props.items.map((item,index) =>{
return <option value={index}>{item}</option>})}
</select>
)
}
}
class Form extends React.Component{
constructor(props){
super(props)
this.state = {first:"",last:"",activity:0,restriction:{a:false,b:false,c:false}}
this.handleChange = this.handleChange.bind(this)
}
handleChange(event){
this.setState({[event.target.name]:event.target.value},()=>{console.log(this.state)})
}
handleCheck(key) {
return function (event) {
var restriction = Object.assign({},this.state.restriction);
restriction[key] = event.target.checked;
this.setState({restriction:restriction},()=>{console.log(this.state)});
}.bind(this);
}
render(){
return(
<form>
<div>
First Name<input name="first" value={this.state.first} onChange={this.handleChange}/>
</div>
<div>
Last Name<input name="last" value={this.state.last} onChange={this.handleChange}/>
</div>
<div>
<input type="checkbox" checked={this.state.restriction.a} onChange={this.handleCheck("a")}/>
<label>a) Dietarty Restriction</label>
</div>
<div>
<input type="checkbox" checked={this.state.restriction.b} onChange={this.handleCheck("b")}/>
<label>b) Physical Disablities</label>
</div>
<div>
<input type="checkbox" checked={this.state.restriction.c} onChange={this.handleCheck("c")}/>
<label>c) Medical Needs</label>
</div>
<div>
<SelectActivity name="activity" items={["Science Lab","Swimming","Painting","Cooking"]} value={this.state.activity} onSelect={this.handleChange}/>
</div>
</form>
)
}
}
ReactDOM.render(
<Form/>,
document.getElementById("root")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id="root"></div>

Initialize my form with redux-form

I am facing trouble with initializing my form with redux-form and the 'initialValues' props. I read a lot posts (for instance here) and I don't manage to get it work...
I see that my initialValues is properly set but my fields are not updated with it... Maybe the issue is in my renderBasicField function but I don't know how to fix this.
Otherwise it could also be something like the prop is not populated yet when the component is rendered... But I don't know what to do to make it work as I must rely on mapStateToProps to feed it.
I saw a lot of post about this kind of issues and unfortunately for me I already set up the enableReinitialize property to true :)
Here is my code :
// My component
class ProfileForm extends React.Component {
render () {
console.log(this.props);
const { handleSubmit } = this.props;
const messageClassname = this.props.errorMessage !== undefined ? stylesShared.errorMessage : this.props.confirmationMessage !== undefined ? stylesShared.confirmationMessage : '';
return (
<div>
<div>
<div>
<form onSubmit={handleSubmit(this.props.onSubmitProfileUpdate)}>
<div>
<h4>Votre profil</h4>
</div>
<div className={messageClassname}>
{this.props.errorMessage &&
<span>{this.props.errorMessage}</span>
}
{this.props.confirmationMessage &&
<span>{this.props.confirmationMessage}</span>
}
</div>
<div>
<Field name='firstname' type='text' label='Prénom' component={renderBasicField} />
</div>
<div>
<Field name='lastname' type='text' label='Nom' component={renderBasicField} />
</div>
<div>
<Field name='email' type='email' label='Email' addon='#' component={renderBasicField} />
</div>
<div>
<Field name='telephone' type='text' label='Téléphone' component={renderBasicField} />
</div>
<div>
<Field name='ranking' className='input-row form-group form-control' options={this.getTennisRankingsOptions()} type='select' component={renderSelectField} />
</div>
<div>
<Field name='city' type='text' label='Ville' component={renderBasicField} />
</div>
<div>
<button className='btn btn-info btn-lg center-block' type='submit'>Mettre à jour</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
const reduxFormDecorator = reduxForm({
form: 'profile',
enableReinitialize: true,
validate: validateProfileForm
});
const mapStateToProps = (state) => {
return {
initialValues: state.userConnection.loadProfile.user
};
};
const reduxConnector = connect(
mapStateToProps,
null
);
export default reduxConnector(reduxFormDecorator(ProfileForm));
And the code to render my field :
// My renderFunction
export const renderBasicField = ({input, meta: {touched, error}, label, type='text', id, addon, styleClasses, handleChange, controlledAsyncValue}) => {
const inputStyles = getInputStyles(input.value, touched, error);
if (controlledAsyncValue !== input.value) {
input.value = controlledAsyncValue;
input.onChange(input.value);
}
return (<div className={inputStyles.container}>
{displayInputLabel(inputStyles.input.idInput, label)}
<div className={addon && 'input-group'}>
{addon && <span className='input-group-addon'>{addon}</span>}
<input
{...input}
className={classNames(styles.basicInputField, styleClasses)}
id={id}
value={input.disabled ? '' : input.value}
onChange={getOnChangeAction(input.onChange, handleChange)}
placeholder={label}
type={type}
aria-describedby={inputStyles.input.ariaDescribedBy}
/>
</div>
{touched && error &&
displayErrorMessage(error)}
</div>);
};
I am wondering if I am ignoring the initialValue with my custom renderBasicField function but in that case, I would I retrieve this value to set my input ?
Thanks a lot for your help ! :)
Try to switch connect and form decorator. It should helps.
export default reduxFormDecorator(reduxConnector(ProfileForm));

Keep code DRY on create/edit form

I have a few inputs that are used in my form for both create and update. I decided to make them a component.
// used for CRU on the event record
import React from 'react';
class Form extends React.Component {
render() {
return (
<div className="slds-form">
<div className="slds-form-element">
<label className="slds-form-element__label">Assigned To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.assigned = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Related To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.related = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Location</label>
<div className="slds-form-element__control">
<input ref={(input) => this.location = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event Start</label>
<div className="slds-form-element__control">
<input ref={(input) => this.start = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event End</label>
<div className="slds-form-element__control">
<input ref={(input) => this.end = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Contact</label>
<div className="slds-form-element__control">
<input ref={(input) => this.contact = input} type="text" className="slds-input" disabled/>
</div>
</div>
<button type="button" className="slds-button slds-button--neutral">Cancel</button>
<button type="submit" className="slds-button slds-button--brand">{this.props.buttonLabel}</button>
</div>
);
}
}
export default Form;
I then attempted to use this component in my <Create /> component.
// used for Create on the event record
import React from 'react';
import Form from './Form';
class Create extends React.Component {
createEvent(e) {
console.log("createEvent() has fired.");
e.preventDefault();
const event = {
assigned: this.assigned.value,
related: this.related.value,
location: this.location.value,
start: this.start.value,
end: this.end.value,
contact: this.contact.value
}
console.log(event);
}
render() {
return (
<form onSubmit={(e) => this.createEvent(e)}>
<Form buttonLabel="Create" />
</form>
);
}
}
export default Create;
When I try to hit the Create button on my <Create /> component I get an error
Uncaught TypeError: Cannot read property 'value' of undefined
at Create.createEvent (webpack:///./src/components/Event/Create.js?:42:32)
at onSubmit (webpack:///./src/components/Event/Create.js?:59:27)
at Object.ReactErrorUtils.invokeGuardedCallback (webpack:///./~/react/lib/ReactErrorUtils.js?:70:16)
at executeDispatch (webpack:///./~/react/lib/EventPluginUtils.js?:89:21)
at Object.executeDispatchesInOrder (webpack:///./~/react/lib/EventPluginUtils.js?:112:5)
at executeDispatchesAndRelease (webpack:///./~/react/lib/EventPluginHub.js?:44:22)
at executeDispatchesAndReleaseTopLevel (webpack:///./~/react/lib/EventPluginHub.js?:55:10)
at Array.forEach (native)
at forEachAccumulated (webpack:///./~/react/lib/forEachAccumulated.js?:25:9)
at Object.processEventQueue (webpack:///./~/react/lib/EventPluginHub.js?:231:7)
I then check the console and see the refs belong in my <Form /> component, and not my <Create /> component.
Is there a way to pass the refs from my child component, <Form />, to its parent, <Create />?
That's a lot of refs! Good news, you really don't need them, at all. As a very very general rule, you should only be using refs if you are interacting with an external library that doesn't "understand" React (d3, Greensock, TinyMCE, etc).
Tackling it in an uncontrolled way can be done like:
const User = (props) => (
<div>
<input name="foo" className="form-control" />
<input name="foo2" className="form-control" />
<button type="submit" className="btn btn-primary">{props.buttonLabel}</button>
</div>
);
class App extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
onSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="container">
<br />
<form onChange={this.onChange} onSubmit={this.onSubmit}>
<User buttonLabel="Create"/>
</form>
</div>
);
}
};
ReactDOM.render(<App />, document.getElementById('app'));
Codepen example:
http://codepen.io/cjke/pen/zNXxga?editors=0010

Rendering new component on click in react

I'm practicing react and trying to render a new component on click of a button. Here the first page is email and the component i want to render contains password page.
class App extends React.Component {
passwordpage(){
return(
<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>
);
};
render() {
return (
<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button type="submit" onClick={this.props.passwordpage} className="loginbutton">Next</button>
</div>
</div>
</form>
);
}
}
ReactDOM.render(<App/>,document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
The simplest is to have the password page already prepared in your render(),
and to show/hide it depending on the component state, that is mutated by the onClick handler, something along those lines:
showPasswordPage() {
this.setState({showPassword: true });
}
render() {
const passwordPage = (<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>);
const mainForm = (<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button type="submit" onClick={this.showPasswordPage} className="loginbutton">Next</button>
</div>
</div>
</form>);
return { this.state.showPassword ? passwordPage : mainForm };
I usually keep some variables in state and change them based on user action.
So in your case I have stored the current active page e.g usernamePage and when user clicks next I show another page in your case it is passwordPage.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isPasswordPage : false,
isUsernamePage : true,
username : "",
password : ""
};
this.enablePasswordPage = this.enablePasswordPage.bind(this);
}
enablePasswordPage() {
this.setState({
isPasswordPage : true,
isUsernamePage : false
});
}
passwordpage(){
return(
<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>
);
};
render() {
var usernameComp = (
<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button onClick={this.enablePasswordPage} className="loginbutton">Next</button>
</div>
</div>
</form>
);
return (
<div>
{ this.state.isUsernamePage ? usernameComp : null }
{ this.state.isPasswordPage ? this.passwordpage() : null }
</div>
);
}
}
ReactDOM.render(<App/>,document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="app"></div>
What you need to do is to make use of react-router and then create separate components for each of the Page that you want to display. That is the best possible way to achieve what you want to do.
You components will look something like
class Home extends React.Component {
render() {
return (
<div>{this.props.children}</div>
)
}
}
class App extends React.Component {
handleClick = (e) => {
e.stopPropagation();
browserHistory.push('/passwordPage');
}
render() {
return (
<form>
<div className="mainapp">
<h2>Email Id</h2>
<input type='email' ref='enteremail'className="inputemail" placeholder='Enter Username' required/>
<div>
<button className="loginbutton" onClick={this.handleClick}>Next</button>
</div>
</div>
</form>
);
}
}
class PasswordPage extends React.Component {
render() {
return (
<form>
<div className="mainapp">
<h2> Password</h2>
<input type='Password' className="inputpassword" placeholder='Enter Password' required/>
<div>
<button type="submit" className="loginbutton">Next</button>
</div>
</div>
</form>
)
}
}
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={Home}>
<IndexRoute component={App} />
<Route path="/passwordPage" component={PasswordPage} />
</Route>
</Router>
)
Look at the react-router docs here

Categories

Resources