I'm using React + Redux, and redux-form for form processing and validation. So far, it's been pretty easy to use and I can easily check the validation state of individual form fields using field.touched and field.error, but I can't seem to find any method or property which will tell me if there are any errors across the entire form. The way React works, any form will generate a bunch of errors as soon as it's loaded, which is why you need to use field.touched to test individual fields.
What I'm looking to do is to have some universal markup displayed if there are any errors anywhere in the form, but only once touched. So really, I was hoping there was something like form.touched and form.error. I have a design in mind for a helper function which will check all fields in a form and return a boolean but I'd prefer to avoid this if possible.
UPDATE:
As per Andy_D's answer, I've updated my code to use the form-level properties dirty
and invalid
but dirty
doesn't seem to update properly. After submitting the form and seeing individual field-level errors, the form is still showing dirty: false
.
Included below is a simplified version of my code as well as the contents of the this.props object after submitting the form.
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
import { makeBooking } from '../actions/index';
class PaymentBooking extends Component {
render() {
const { fields: { school }, handleSubmit } = this.props;
return (
<form className="form-horizontal" onSubmit={handleSubmit(this.props.makeBooking)}>
{
console.log(this)
}
{
this.props.dirty && this.props.invalid ? <div className="alert alert-danger" role="alert">Test error wrapper</div> : ''
}
<h2>Make a New Payment Booking</h2>
<div className="panel panel-default">
<div className="panel-heading">Payment Information</div>
<div className="panel-body">
<div className={`form-group ${school.touched && school.invalid ? 'has-error' : ''}`}>
<label htmlFor="school" className="col-lg-2 control-label">Your School</label>
<div className="col-lg-10">
<select name="school" className="form-control" {...school}>
<option value="MIT">MIT</option>
<option value="Stanford">Stanford</option>
<option value="Arizona">Arizona</option>
</select>
</div>
</div>
</div>
</div>
</div>
<div className="form-submit">
<button type="submit" className="btn btn-primary">Book a Payment</button>
</div>
</form>
);
}
}
function validate(values) {
const errors = {};
if (!values.school)
errors.school = 'School is a required field';
return errors;
}
export default reduxForm({
form: 'PaymentBookingForm',
fields: ['school'],
validate
}, null, {makeBooking})(PaymentBooking);
this.props after submit:
{
"readonly": false,
"asyncValidating": false,
"dirty": false,
"errors": {
"school": "School is a required field"
},
"fields": {
"school": {
"name": "school",
"defaultChecked": false,
"valid": false,
"invalid": true,
"dirty": false,
"pristine": true,
"error": "School is a required field",
"active": false,
"touched": true,
"visited": false
}
},
"invalid": true,
"pristine": true,
"submitting": false,
"submitFailed": true,
"valid": false,
"values": {}
}
It's there in the props for you - you're looking for the form-level props pristine
and valid
.
After submit, pristine
will reset, but if the request is unsuccessful, you'll get a submitFailed
prop.
(!pristine || submitFailed) && !valid && <ErrorMessage />
There are also props for the inverses, so you could use
(dirty || submitFailed) && invalid
As I mentioned in my comment, I would prevent submit if the form is invalid.
<button
type="submit"
className="btn btn-primary"
disabled={pristine || invalid}
>Book a Payment</button>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With