Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if any errors exist in redux-form

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": {}
}
like image 280
T Nguyen Avatar asked Feb 26 '17 08:02

T Nguyen


1 Answers

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>
like image 134
Andy_D Avatar answered Oct 02 '22 12:10

Andy_D