how to provide validations for react js form - reactjs

How to provide validations for react js form.
I have taken form with two fields. if two fields are enabled then only need to enable save button.
import React from 'react'
import { Button, Checkbox, Form } from 'semantic-ui-react'
const FormExampleForm = () => (
<Form>
<Form.Field>
<label>First Name</label>
<input placeholder='First Name' />
</Form.Field>
<Form.Field>
<label>Last Name</label>
<input placeholder='Last Name' />
</Form.Field>
<Form.Field>
<Checkbox label='I agree to the Terms and Conditions' />
</Form.Field>
<Button type='submit'>Submit</Button>
</Form>
)
export default FormExampleForm

In redux forms 6.7 there's a simple property called pristine which can be used to do this. But if the user enters some value in at least one input field the submit button gets activated. To achieve that you may need to do something like this.
render() {
// const { handleSubmit } = this.props;
const {handleSubmit, pristine, reset, submitting} = this.props
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name"/>
</div>
</div>
<button type="submit" className="btn btn-primary" disabled={pristine || submitting}>Submit</button>
</form>
);
}
}
But if you need to enable submit button, say when the user inputs values in 2 given fields or so, then this becomes complex. You need to do something like this. Here's my sample usecase. The form has 3 fields firstName, lastName and age. The submit button gets activated only if the user enters values for firstName and lastName input fields here. Please check out the following code.
import React, { Component } from 'react';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import { connect } from 'react-redux';
class UserNew extends Component {
constructor(props) {
super(props);
this.isSubmitEnabled = this.isSubmitEnabled.bind(this);
}
onSubmit(values) {
console.log(values);
}
isSubmitEnabled() {
// Access field values here and validate them
const firstName = this.props.firstNameValue;
const lastName = this.props.lastNameValue;
if(firstName && lastName){
return true;
}
return false;
}
render() {
const { handleSubmit } = this.props;
const isEnabled = this.isSubmitEnabled();
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" />
</div>
</div>
<div>
<label>Age</label>
<div>
<Field name="age" component="input" type="text" />
</div>
</div>
<button type="submit" className="btn btn-primary" disabled={!isEnabled}>Submit</button>
</form>
);
}
}
UserNew = reduxForm({
form: 'UserNewForm'
})(
UserNew
);
// Decorate with connect to read form values
const selector = formValueSelector('UserNewForm') // <-- same as form name
UserNew = connect(state => {
const firstNameValue = selector(state, 'firstName')
const lastNameValue = selector(state, 'lastName')
return {
firstNameValue,
lastNameValue,
}
})(UserNew)
export default UserNew;
To access field values you need to use formValueSelector in ReduxForms. For that you need to connect your form to redux store using connect helper.
Hope this helps. Happy coding !

Either you can use Redux-form as its not used in above code, so you can write custom JS validation code. For this you need to follow below
Initialise state in
contructor(){
this.state{
first_name: null,
last_name: null,
}
}
Change state of every input element onChange onChange={()=>this.setState({first_name: event.target.value})}
Now add onClick property to <Button onClick={this.handleSubmit} />
inside handleSubmit() you can get values through local state of component and add validation rules like
if(this.state.first_name =="") {
console.log("Enter first name")
}

Related

why the page refresh on button click in react?

could you please tell me why the page refresh on button click in react ? I enter something in input field and press button, my page is refresh
I want to get the value of form field
https://codesandbox.io/s/green-frost-414qi
class ContactForm extends React.Component {
handleSubmit = values => {
// print the form values to the console
console.log(values);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
It's standard behavior for forms to refresh the page after submit events. To stop this you can add event.preventDefault()
handleSubmit = event => {
event.preventDefault()
console.log(event.target.firstName.value); //get value from input with name of firstName
};
With Redux-Forms, in order to get the values object and not have the page refresh, we have to use the event-handler that's been created for us by Redux-form. It's created when we pass an onSubmit prop like so to the Form component:
<ContactRForm onSubmit={this.submit} />
Interestingly enough, that handler is now available through the prop handleSubmit(), which I expect has its own event.preventDefault() built in.
Try adding this to your Form component-code:
import React from "react";
import { Field, reduxForm } from "redux-form";
class ContactForm extends React.Component {
render() {
return (
<form onSubmit={this.props.handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text" />
<label htmlFor="lastname">Last Name</label>
<Field name="lastname" component="input" type="text" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
Now the same functionality of the original submit function occurs and the page does not refresh. :)
You can achieve this using below changes.
class ContactForm extends React.Component {
constructor(props){
super(props);
this.state = {
fieldValue : ''
}
this.updateInput = this.updateInput.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
updateInput(event){
this.setState({username : event.target.value})
}
handleSubmit = event=> {
// print the form values to the console
event.preventDefault() // this is used to prevent the form submission
console.log('Your input value is: ' + this.state.username) // your input field value
};
render() {
return (
<form>
<div>
<label htmlFor="firstName">First Name</label>
<Field value={input} onChange={this.updateInput} /> // set the input value
</div>
<button type="submit" onClick={this.handleSubmit} >Submit</button>
</form>
);
}
}
const ContactRForm = reduxForm({
// a unique name for the form
form: "contact"
})(ContactForm);
export default ContactRForm;
This is default behavior of HTML forms to refresh page on submit button. You can stop refresh by adding event.preventDefault();
For more details you can read ReactJS Form documentation
handleSubmit = e => {
event.preventDefault()
// get form value by accessing target values
console.log(e.target.firstName.value);
};

How to use formik along with a stateful react component

I have just started learning reactjs. I came across formik and yup while searching for form validation. Most of the examples that i have gone through so far are talking about stateless components. So I would like to know how can I use formik and yup in a stateful component?
I have got a simple employee details form with email,first name, last name, phone and city. The data for the form is loaded from the database. Once the data is loaded, then user can edit and save it to db. Could you please help me to add formik and yup into my project by adding validation for all my above fields? My Code is also present here https://codesandbox.io/s/l26rqyx6j7
My form is given below EmpJobDetailsForm.js
import React from "react";
import { getEmpDetails } from "./APIUtils";
import { withFormik, Form, Field } from "formik";
import Yup from "yup";
class EmpJobDetailsForm extends React.Component {
state = {
data: {}
};
componentWillMount() {
this.getData();
}
getData = () => {
let response = getEmpDetails();
this.setState({ data: response });
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input type="email" name="email" value={this.state.data.email} />
</div>
<div>
<label htmlFor="firstName">First Name</label>
<input
type="text"
name="firstName"
value={this.state.data.firstName}
/>
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<input
type="text"
name="lastName"
value={this.state.data.lastName}
/>
</div>
<div>
<label htmlFor="phone">Phone</label>
<input type="text" name="phone" value={this.state.data.phone} />
</div>
<div>
<label htmlFor="city">City</label>
<input type="text" name="city" value={this.state.data.city} />
</div>
<div>
<button type="button" className="outline">
Reset
</button>
<button type="submit">Submit</button>
</div>
</form>
</div>
);
}
}
export default EmpJobDetailsForm;
I have a simple APIUtils.js. It is very basic and i will add code to fetch data from db here.
export function getEmpDetails() {
var employeeData = {};
employeeData.email = "test#gmail.com";
employeeData.firstName = "Luis";
employeeData.middleName = "John";
employeeData.lastName = "Nakano";
employeeData.phone = "1112223333";
employeeData.city = "Dallas";
return employeeData;
}
Appreciate your help.
Thanks
Formik is stateful, it's first goal is to "Getting values in and out of form state" (without using Redux-Form).
A cleaner way to do this would be to use a Formik form and to add your fetched data as initalValues (but first remove all the value attributes from your current inputs).
You can also take a look at the 'withFormik' higher-order component and particularly the mapsPropsToValues option.

How to handleSubmit with a redux-form

I'm working to use redux-form for the first time. I am able to render the form but I have not been able to handle the submit. While I eventually want to send the data to the server, at this point, I'm simply trying to console log the form field values. I'm getting the error:
Error: You must either pass handleSubmit() an onSubmit function or pass onSubmit as a prop
Here's my Profile.jsx file
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {withAuth} from 'react-devise';
import { Field, reduxForm } from 'redux-form';
class Profile extends Component {
handleSubmit(data) {
console.log('Submission received!', data);
}
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text"/>
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" component="input" type="text"/>
</div>
<div>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email"/>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
// Decorate the form component
Profile = reduxForm({
form: 'profile' // a unique name for this form
})(Profile);
const mapStateToProps = state => {
return {
currentUser: state.currentUser
};
};
export default connect(mapStateToProps)(withAuth(Profile));
How can I handle the submitted values in a way where I can eventually send them to my API?
Redux-Form decorates your component with handleSubmit prop. According to docs it's:
a function meant to be passed to <form onSubmit={handleSubmit}> or to
<button onClick={handleSubmit}>. It will run validation, both sync and
async, and, if the form is valid, it will call
this.props.onSubmit(data) with the contents of the form data.
Optionally, you may also pass your onSubmit function to handleSubmit
which will take the place of the onSubmit prop. For example:
So if your component doesn't have onSubmit property you have to 'manually' pass your submit handler to handleSubmit function. Please try this:
<form onSubmit={this.props.handleSubmit(this.handleSubmit.bind(this))}>
Please don't confuse your handleSubmit method with prop passed from Redux-Form with the same name.
(Posted solution on behalf of the question author to move it to the answer space).
Working code:
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {withAuth} from 'react-devise';
import { Field, reduxForm } from 'redux-form';
class Profile extends Component {
handleSubmit(data) {
console.log('Submission received!', data);
}
render() {
return (
<form onSubmit={this.props.handleSubmit(this.handleSubmit.bind(this))}>
<div>
<label htmlFor="firstName">First Name</label>
<Field name="firstName" component="input" type="text"/>
</div>
<div>
<label htmlFor="lastName">Last Name</label>
<Field name="lastName" component="input" type="text"/>
</div>
<div>
<label htmlFor="email">Email</label>
<Field name="email" component="input" type="email"/>
</div>
<button type="submit">Submit</button>
</form>
);
}
}
// Decorate the form component
Profile = reduxForm({
form: 'profile' // a unique name for this form
})(Profile);
const mapStateToProps = state => {
return {
currentUser: state.currentUser
};
};
export default connect(mapStateToProps)(withAuth(Profile));

Why can't I type in my fields?

I am using redux-form and I cannot type inside of my inputs after I add the initialize method and componentDidUpdate(). When I try to type in my email no characters appear. I am guessing all the inputs become controlled? If so how would I handle that?
import { reduxForm, Field, initialize } from 'redux-form';
const CustomComponent = function(field) {
return(
<div>
<input { ...field.input } type={field.type} placeholder={field.placeholder} />
</div>
);
}
//class instantiation
componentDidUpdate(){
this.handleInitialize();
}
handleInitialize() {
const initData = {
"name": this.props.name
};
this.props.initialize(initData);
}
render() {
const { handleSubmit } = this.props;
return (
<div>
<form onSubmit={handleSubmit(this.onSubmit)}>
<div>
<Field name="name" component={CustomComponent} type="text" placeholder="Name" />
<Field name="email" component={CustomComponent} type="email" placeholder="Email" />
</div>
<button type="submit">Submit</button>
</form>
</div>
);
}
You can't define your CustomComponent inside the render() method. That will cause your component to lose focus when you first start typing into an input.
Have you set up the reducer properly in your Redux config?

Submitting redux form values

I am new to react and redux technology. now started building an application that contains several redux forms. We want to submit simple form with values.
For ex: login form
Username : text input field
Password: text input field
Submit button
After entering values in fields and click on submit button i want to get the username and password field values in object or json data .. so that I can store it to my server with POST method.
Right now we are using handleSubmit(), but data is not coming as object
1 - The best practice to deal with input values are making them controlled. Which means :
Instead of
<input type='password' />
You do :
<input
type='password'
value={password}
onChange={ event => myInputHandler( event.target.value ) }
/>
The value might come from your state, redux state or as a props etc.
Your handler function differs according to where you store it.
I will give you an example with react state :
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
So whenever someone types, your onChange handler will be called, so that your react state will update with the input ( event.target.value ).
2 - If you need these values when a user submits, then you need to wrap these input fields within a form element and attach a onSubmit handler.
onSubmitHandler( event ){
event.preventDefault()
let password = this.state.password
// use password or other input fields, send to server etc.
}
<form onSubmit={ event => this.onSubmitHandler(event) }>
<input
type='password'
value={this.state.password}
onChange={ event => this.setState({ password : event.target.value }) }
/>
</form>
Hope you get what you need.
If you are using redux to store state then use redux-from then use redux from
import React from 'react'
import {Field, reduxForm} from 'redux-form'
const SimpleForm = props => {
const {handleSubmit, submitting} = props return (
<form onSubmit={handleSubmit(e=>console.log('your form detail here', e))}>
<div>
<label>First Name</label>
<div>
<Field name="firstName" component="input" type="text" placeholder="First Name" />
</div>
</div>
<div>
<label>Last Name</label>
<div>
<Field name="lastName" component="input" type="text" placeholder="Last Name" />
</div>
</div>
<div>
<button type="submit" disabled={pristine || submitting}>Submit</button>
</div>
</form>
) }
export default reduxForm({ form: 'simple'})(SimpleForm)
Go here for more detail
https://redux-form.com
I put the name of the input as the key that I want to use.
Then each time the input changes I destructure the event passed to the onChange function, and I use the name,value to update the state.
On form submit make sure to use preventDefault(); in order to avoid the page refreshing.
import React, { Component } from 'react'
class FormExample extends Component {
constructor(props){
super(props)
this.state = {
formData: {}
}
}
handleInputChange = ({ target: { name,value } }) => {
this.setState({
formData: {
...this.state.formData,
[name]: value
}
})
}
handleFormSubmit = e => {
e.preventDefault()
// This is your object
console.log(this.state.formData)
}
render() {
return(
<div>
<Form
handleSubmit={this.handleFormSubmit}
handleChange={this.handleInputChange}
/>
</div>
)
}
}
const Form = ({ handleSubmit, handleChange }) => (
<form onSubmit={handleSubmit}>
<input onChange={handleChange} name="username" type="text" placeholder="Username" />
<input onChange={handleChange} name="password" type="password" placeholder="Password" />
<button>Submit</button>
</form>
)
export default FormExample

Resources