How to get form data from input fields in React - javascript

The constructor and function:
constructor(props) {
super(props);
this.state = {
tagline: 'We rank what people are talking about.',
year: new Date().getFullYear()
};
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onFormSubmit(e) {
console.log('onFormSubmit', e)
console.log('this.state', this.state);
};
The form (classNames removed for clarity):
<form onSubmit={ this.onFormSubmit }>
<div className="fl w100">
<div>
<input type="text" id="email" value={ this.state.email }/>
<label htmlFor="email">Email</label>
</div>
</div>
<div className="fl w100">
<div>
<input type="password" id="password" value={ this.state.password }/>
<label htmlFor="password">Password</label>
</div>
</div>
<button type="submit">
Login
</button>
</form>
This is what logs out, note no email or password information:
Full Login component code
import React from 'react';
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
tagline: 'We rank what people are talking about.',
year: new Date().getFullYear()
};
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onFormSubmit(e) {
console.log('onFormSubmit', e)
console.log('this.state', this.state);
};
render() {
return (<div className="app">
<div className="welcome">
<header>
<div className="wikitags-logo">
<img src="imgs/wikitags-logo.png"/>
</div>
<h2>Admin Portal</h2>
<p>{ this.state.tagline }</p>
</header>
<section className="login-form">
<form onSubmit={ this.onFormSubmit }>
<div className="fl w100">
<div className="mdl-textfield mdl-js-textfield">
<input className="mdl-textfield__input" type="text" id="email" value={ this.state.email }/>
<label className="mdl-textfield__label" htmlFor="email">Email</label>
</div>
</div>
<div className="fl w100">
<div className="mdl-textfield mdl-js-textfield">
<input className="mdl-textfield__input" type="password" id="password" value={ this.state.password }/>
<label className="mdl-textfield__label" htmlFor="password">Password</label>
</div>
</div>
<button type="submit" className="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--accent">
Login
</button>
</form>
</section>
<footer>
© { this.state.year } WikiTags
</footer>
</div>
</div>);
}
}
export default Login;

Suggestions:
1. You are using value property with input fields but you didn't defined the onChange method so your input fields will be read-only because state value will not get updated.
2. You need to define a onChange event will all the input fields or make them uncontrolled element by removing the value property.
3. In case of uncontrolled element define the ref to each field and to access the value use this.ref_name.value.
By Defining the onChange event:
Define the name property to each input element (name should be same as state variable name it will help to update the state and we can handle all the change in single onChange function) like this:
<input type="text" name='value' value={this.state.value} onChange={(e) => this.handleChange(e)} />
handleChange(e){
this.setState({[e.target.name]: e.target.value})
}
By Uncotrolled element:
<input type="text" ref={el => this.el = el} />
Now inside onSubmit function use this.el.value to access he values of this input field.
Check this answer for reference: https://stackoverflow.com/a/43695213/5185595

You are not getting email or password information because you're passing in the state console.log('this.state', this.state); and you haven't set a state for the email and password.
Now, you got two options:
Set the state and get the form info from there
Pass the input value to a function that handles the info
For option 1, you'll need to set a state for your email and password (although setting a state for a password is not recommended) and an onChange event handler on the input(s).
Set up your onChange event handlers.
<form onSubmit={ this.onFormSubmit }>
<input type="text" id="email" onChange={this.handleEmailChange} value={ this.state.email } />
<input type="password" id="password" onChange={this.handlePasswordChange} value={ this.state.password } />
<button type="submit">
Login
</button>
</form>
And the functions to set the email and password states.
handleEmailChange(event) {
this.setState({ email: event.target.value });
}
handlePasswordChange(event) {
this.setState({ password: event.target.value });
}
And don't forget to initialize the state for your email and password in the constructor and bind the functions.
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
this.handleEmailChange = this.handleEmailChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
}
And you're done! Then on the onFormSubmit function just access the email and password values from the state this.state.email and this.state.password and do whatever you like.
Now for option 2, you can just pass in the event.target.value of the inputs, those are the values for the email and the password, and pass those values to a form event handler onSubmit function, from there you can do whatever you want (set the state or update the email and password, change them, whatever).
<form onSubmit={ this.onFormSubmit }>
<input type="text" id="email" name="theEmail" />
<input type="password" id="password" name="thePassword" />
<button type="submit">
Login
</button>
</form>
And the onFormSubmit function.
onFormSubmit(event) {
const email = event.target.theEmail.value;
const password = event.target.thePassword.value;
// do stuff
console.log('Email:', email);
console.log('Password:', password);
};
The easier and recommended way to accomplish what you're trying to do is the option 2.
Remember, the less state your app handles the better.

So how I would approach this is to store the values in your state using what is called a controlled component. Making a controlled component is very simple, this is a basic implementation:
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
The key here is the handleChange function, and the onChange attribute. Every time the input field changes, the handleChange function is going to be called and the state will be updated.
You can find more info form the documentation here: https://facebook.github.io/react/docs/forms.html

Related

Clearing form input after submitting using setState

UPDATE : There is a problem in the FormInput component, the state is changing but the new state passed as props to FormInput is not being reflected.
I was creating this contact form in react and I wanted it to clear after submission.
After rigorous searching on the web, I couldn't find why my this.setState is not clearing the input fields as I'm changing all the inputs to an empty string. Take a look:
class contactPage extends React.Component{
constructor(props){
super(props);
this.state = {
name :'',
email : '',
subject : '',
message : ''
}
}
handleChange = (e) =>{
const {name,value} = e.target;
this.setState({
[name] : value
})
}
handleSubmit = (e) => {
e.preventDefault();
this.setState({
name :'',
email : '',
subject : '',
message : ''
});
}
render(){
const { name,email,subject,message } = this.state;
return(
<div className='contact-page'>
<h1 className='title'> Contact Page </h1>
<div className='form-container'>
<form onSubmit={this.handleSubmit}>
<div className='input-container'>
<div className='form-input'>
<FormInput handleChange = {this.handleChange} value={name} type='text' name ='name' label='Full Name'/>
</div>
<div className='form-input'>
<FormInput handleChange = {this.handleChange} value={email} type='email' name ='email' label='Email'/>
</div>
<div className='form-input'>
<FormInput handleChange = {this.handleChange} value={subject} type='text' name ='subject' label='Subject'/>
</div>
<div className='form-input'>
<FormInput handleChange = {this.handleChange} value={message} name ='text-area' label='Message'/>
</div>
<div className='form-input'>
<CustomButton
type='submit' value='SEND' >SEND</CustomButton>
</div>
</div>
</form>
</div>
</div>)
}
}
I am not very confidant that the state isn't chaging, it might be a problem with your inputs
I've done just the same component, using native inputs instead, and it works perfectly

How to pass the default value back as input value if you don't want the value to be changed?

I have assigned default values to the input tag. When I try to submit without changing the values of the input tag, the value passed is undefined.
What I want is that if the input value is changed, to update the state value with the new value and if the input tag value is not changed, then to pass the default value to the state.
I am new to React.
import React, { Component } from 'react';
import Firebase from '../Firebase';
import _ from 'lodash';
import '../App.css';
class Modify extends Component {
constructor(props) {
super(props);
//state
this.state = {
personDetails: {},
detail: ''
};
//bind
this.renderData = this.renderData.bind(this);
this.handleChange = this.handleChange.bind(this);
this.saveEdit = this.saveEdit.bind(this);
}
//lifecycle
componentDidMount() {
Firebase.database().ref('/nannydetails').on('value', (snapshot) => {
this.setState({
personDetails: snapshot.val()
})
})
}
//handle change
handleChange(event) {
this.setState({
[event.target.name]: event.target.value.toLowerCase()
});
}
//render data
renderData() {
return _.map(this.state.personDetails, (personDetail, key) => {
return(
<div className="pt-2 pb-1 m-2 border border-dark bg-warning row" key={key}>
<div className="col-md-3 col-xs-3 text-right">
<img src={require('./profile.png')} alt="cam"/>
</div>
<div className="col-md-9 col-xs-9 p-2">
<div className="headline">
<h1>Full Name: </h1>
<input className="form-control" type="text" name="fullName" defaultValue={personDetail.fullname} onChange={this.handleChange}/>
</div>
<div className="headline">
<h1>Contact Number: </h1>
<input className="form-control" type="text" name="phone" defaultValue={personDetail.phone} onChange={this.handleChange}/>
</div>
<div className="headline">
<h1>Experience: </h1>
<input className="form-control" type="text" name="experience" defaultValue={personDetail.experience} onChange={this.handleChange}/>
</div>
<div className="headline">
<h1>City: </h1>
<input className="form-control" type="text" name="city" defaultValue={personDetail.city} onChange={this.handleChange}/>
</div>
<div className="headline">
<h1>State: </h1>
<input className="form-control" type="text" name="state" defaultValue={personDetail.state} onChange={this.handleChange}/>
</div>
<button className="btn btn-success" type="button" onClick={() => this.saveEdit(key)}><i className="fa fa-pencil-square-o"></i> Save Edit</button>
<button className="btn btn-danger" type="button" onClick={() => this.handleDelete(key)}><i className="fa fa-trash"></i> Delete</button>
</div>
</div>
)
});
}
//handle save edit
saveEdit(key) {
// Firebase.database().ref(`/nannydetails/${key}`).push({
// fullname: this.state.fullname,
// phone: this.state.phone,
// experience: this.state.experience,
// city: this.state.city,
// state: this.state.state
// });
console.log(this.state.fullname);
console.log(this.state.phone);
console.log(this.state.experience);
console.log(this.state.city);
console.log(this.state.state);
}
//handle delete
handleDelete(key) {
const user= Firebase.database().ref(`/nannydetails/${key}`);
user.remove();
}
render() {
return (
<div className="container mt-4">
{this.renderData()}
</div>
);
}
}
export default Modify;
Update the change handler to update/mutate the existing state instead of adding a new property(key), i.e. on this.state.personDetails.X vs. this.state.X
//handle change
handleChange(event) {
// update the personDetails object you set in state on mount
const newPersonDetails = { ...this.state.personDetails };
newPersonDetails[event.target.name] = event.target.value.toLowerCase();
this.setState({
personDetails: newPersonDetails,
});
}
Make this as a controlled component. Provide a initial state in you component and all the updated will done into the state & that will directly reflect into your component.
Initial State:
this.state = {
personDetails: {
fullname :'test'
},
detail: ''
};
Input Field
input className="form-control" type="text" name="fullName" value={this.state.personDetail.fullname} onChange={this.handleChange}
onChange is only triggered when the value of input changes. The defaultValue can be defined in the initial state, and the defaultValue is overwritten when the value of input changes.
The best way to approach is to have a main component take data from any api (firebase in your case) and second child component which will be responsible to take input as props and return input(default/modified) on form action(submit). That way if data changes you get modified data else the default one.
class FormComp extends React.Component {
constructor(props) {
super(props);
this.state = {
name: this.props.form.name,
};
this.submit = this.submit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
submit(e) {
e.preventDefault();
console.log(this.state);
}
handleChange(e) {
this.setState({name: e.target.value});
}
handleChan
render() {
return (
<div>
<form onSubmit={this.submit}>
<input
type="text"
value={this.state.name}
onChange={this.handleChange}
/>
<button type="submit">Submit</button>
</form>
</div>
);
}
}
Refer to that fiddle for example. https://jsfiddle.net/papish19/ys6utv3k/7/

How to use onchange on 2 input fields in React

I am trying to catch 2 input field's value but none of the input fields is working.
when I comment second Input field than the first one works properly.
state = { zipcode: null, city: "" };
onFormSubmit = event => {
event.preventDefault();
//Callback
this.props.onEnter(this.state.zipcode);
};
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input
type="number"
className={`form-control`}
placeholder="Enter ZIP code"
name="zipcode"
onChange={this.handleChange} />
<input
type="text"
className={`form-control`}
placeholder="Enter Zip-code"
name="city"
onChange={this.handleChange}/>
</form>
</div>
);
}
}
When I hit enter after entering a query in the first input field I get no output and no error.
I tried below code and it worked just fine. Maybe there is something wrong with your callback function. Because on form submission you are getting the correct values.
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {
zipcode: null,
city: ""
}
}
onFormSubmit = event => {
event.preventDefault();
//Callback
console.log(this.state);
};
handleChange = event => {
this.setState({ [event.target.name]: event.target.value });
}
render() {
return (
<div>
<form onSubmit={this.onFormSubmit}>
<input
type="number"
className={`form-control`}
placeholder="Enter ZIP code"
name="zipcode"
onChange={this.handleChange} />
<input
type="text"
className={`form-control`}
placeholder="Enter Zip-code"
name="city"
onChange={this.handleChange}/>
<input type="submit" value="submit" />
</form>
</div>
);
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
Here is the jsfiddle link with your code. Check in the inspect element after clicking on the submit button.
It works.
https://jsfiddle.net/t4o0xawr/1/

Having issues with my onClick on a registration form

New to react so I apologize if the solution obvious. Working on a registration form that should create a new account on submit using ajax. I know that I'm supposed to use onChange to gather the information is submitted. After seeing a number of examples I am still unable to get my code to work.
I know that the ajax call for POST works because I put in information myself on vscode to test if on submit it will create which it did. I am having issues with the transition from onChange to my submit form. Hope that was clear. Thank you
I've tried creating a onChange function for my registration template. I am unable to get the results that I've been hoping for
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
payload: {
firstName: "",
lastName: "",
email: "",
password: "",
passwordConfirm: ""
}
};
}
handleChange = event => {
let name = event.target.name;
let value = event.target.value;
this.setState({
[name]: value,
[name]: value,
[name]: value,
[name]: value,
[name]: value
});
};
onClickHandler = evt => {
evt.preventDefault();
let payload = this.state;
console.log(payload);
debugger;
registerService
.register(payload)
.then(this.onActionSuccess)
.catch(this.onActionError);
};
onActionSuccess = response => {
console.log(response);
};
onActionError = errResponse => {
console.log(errResponse);
};
<!-- -->
render() {
return (
<main role="main">
<div className="container">
<h1 id="title" align="center">
Register User
</h1>
</div>
<div className="container">
<div className="col-sm-4 col-sm offset-4">
<form className="form">
<div className="form-group">
<label htmlFor="this.state.firstName">First Name</label>
<input
placeholder="First Name"
type="text"
id="this.state.firstName"
className="form-control"
name="firstName"
value={this.state.firstName}
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<label htmlFor="this.state.lastName">Last Name</label>
<input
placeholder="last Name"
type="text"
id="this.state. lastName"
className="form-control"
value={this.state.lastName}
onChange={this.handleChange}
/>
<div className="form-group">
<label htmlFor="register-email">Email</label>
<input
placeholder="Enter Email"
type="text"
className="form-control"
id="register-email"
value={this.state.email}
onChange={this.handleChange}
/>
</div>
</div>
<div className="form-group">
<label htmlFor="register-password">Password</label>
<input
placeholder="Password"
type="password"
id="register-password"
`enter code here`className="form-control"
value={this.state.password}
onChange={this.handleChange}
/>
</div>
<div className="form-group">
<label htmlFor="register-passwordConfirm">
Confirm Password
</label>
<input
placeholder="Confirm Password"
type="password"
id="register-passwordConfirm"
className="form-control"
value={this.state.passwordConfirm}
onChange={this.handleChange}
/>
</div>
<button onClick={this.onClickHandler} className="btn btn-
primary">
Submit Form
</button>
I am expecting to create a new profile when clicking submit via POST ajax call
Your handleChange function should be
handleChange = event => {
let { name, value } = event.target;
this.setState({
[name]: value,
});
};
You always call your handleChange once at a time. Every time you change something on the input, the function gets different name and different value, which is suffice to add/update the your state.
And I noticed that you also have payload object in state. Modify the state like
this.state = {
firstname: '',
....
}
If you really want to use like
this.state = {
payload: {
firstName: '',
....
}
};
Your onChange function should look like,
handleChange = event => {
let { name, value } = event.target;
this.setState({
payload: {
...this.state.payload, // don't forget to copy all the other values
[name]: value,
}
});
};

Form Submit using reactjs

I am new in reactjs. I am creating a sample project using reactjs. First I am getting error like state is null. After setting intial state i am getting error
I got Warning: valueLink prop on input is deprecated; set value and onChange instead
I know there are many question related to this but my problem is not solved please help.
Here is code:
import React, {Component} from 'react';
import {Link} from 'react-router'
import validator from 'validator';
import LinkedStateMixin from 'react-addons-linked-state-mixin';
module.exports = React.createClass({
mixins: [LinkedStateMixin],
getInitialState() {
return {};
},
saveData: function(){
//console.log(this.state)
},
render () {
return (
<form>
<div className="page-content container">
<div className="row">
<div className="col-md-4 col-md-offset-4">
<div className="login-wrapper">
<div className="box">
<div className="content-wrap">
<h6>Sign Up</h6>
<input className="form-control" name ="email" placeholder="E-mail address" type="text" valueLink={this.linkState('email')}/>
<input className="form-control" name="password" placeholder="Password" type="password"/>
<input className="form-control" placeholder="Confirm Password" type="password" />
<div className="action">
<button type="button" className ="btn btn-primary signup" onClick={this.saveData}>Sign Up</button>
</div>
</div>
</div>
<div className="already">
<p>Have an account already?</p>
<Link to ="/reactApp/">Login</Link>
</div>
</div>
</div>
</div>
</div>
</form>
)
}
});
Please read more about the fundamentals of React and handling state in forms in the React documentation. No mixins or anything complicated required. Also as stated above "ReactLink is deprecated as of React v15. The recommendation is to explicitly set the value and change handler, instead of using ReactLink."
Each of your text inputs should have a change handler just like the error message says... There are many ways you could accomplish this but below is a basic example. Check out the snippet below in a fiddle here https://jsfiddle.net/09623oae/
React.createClass({
getInitialState: function() {
return({
email: "",
password: "",
passwordConfirmation: ""
})
},
submitForm: function(e) {
e.preventDefault()
console.log(this.state)
},
validateEmail: function(e) {
this.setState({email: e.target.value})
},
validatePassword: function(e) {
this.setState({password: e.target.value})
},
confirmPassword: function(e) {
this.setState({passwordConfirmation: e.target.value})
},
render: function() {
return (
<form onSubmit={this.submitForm}>
<input
type="text"
value={this.state.email}
onChange={this.validateEmail}
placeholder="email"
/>
<input
type="password"
value={this.state.password}
onChange={this.validatePassword}
placeholder="password"
/>
<input
type="password"
value={this.state.passwordConfirmation}
onChange={this.confirmPassword}
placeholder="confirm"
/>
</form>
)
}
});
Solution
You cannot use valueLink anymore, instead use onChange react event to listen for input change, and value to set the changed value.
class MyForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'Hello!'};
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
return (
<input
type="text"
value={this.state.value}
onChange={this.handleChange}
/>
);
}
Clarification
Notice that since the value is set from a state, it will only get updated from changing the attached state, writing in the input does nothing, unless you listen for the input changed (via onChange event) and update the state accordingly.
source: from React documentation
You should set your state to atleast empty initially, if you want to access it at a later point of time. Something similar to below will do
getInitialState() {
return {};
},
ReactLink Without valueLink
You can change with
<input type="text" value={valueLink.value} onChange={handleChange} />
Reference:
https://facebook.github.io/react/docs/two-way-binding-helpers.html
This warning happens because the React Link was deprecated in React 0.15:
ReactLink is deprecated as of React v15. The recommendation is to
explicitly set the value and change handler, instead of using
ReactLink.
So, instead of use this.linkState('email') and valueLink:
<input className="form-control"
name ="email"
placeholder="E-mail address"
type="text"
valueLink={this.linkState('email')}/>
Use this.state.email and an onChange function:
callThisWhenChangeEmail: function(emailFromInput) {
this.setState({
email: emailFromInput
});
},
render () {
/* the existent code above */
<input className="form-control"
name ="email"
placeholder="E-mail address"
type="text"
value={this.state.email}
onChange={this.callThisWhenChangeEmail}/>
/* the existent code below */
}
When the user type some e-mail in the input, the function callThisWhenChangeEmail is called, receiving the e-mail as parameter (emailFromInput). So, you only need to set this e-mail in the state.

Categories

Resources