React-jsonschema-form: Validate onBlur?

Created on 20 Jun 2017  路  14Comments  路  Source: rjsf-team/react-jsonschema-form

Prerequisites

Description

Is it possible to validate a field on Blur event? I would like to do that for, for example, email input.

Most helpful comment

Why was this closed? This should be kept open and a prop should be added to the <Form> so that this feature can be toggled, just like liveValidate. Validating on blur is a very common case.

All 14 comments

I have the same question.

@eddyzhang1986 Its not possible to do so. I recommend you to create your own implementation of jsonschema generator, its not hard and you ll have all flexibility you need.

A demo of OO solution for validate onBlur for the whole form.

import Form from 'react-jsonschema-form';
class BlurForm extends Form {
  constructor(props) {
    super(props);
    const superOnBlur = this.onBlur;
    this.onBlur = (...args) => {
      const { formData } = this.state;
      const { errors, errorSchema } = this.validate(formData);
      this.setState({ errors, errorSchema },()=>superOnBlur(...args));
    }
  }
}

The rest is the same, just don't enable live validation.

My experience was that the on blur is unreliable. The on blur event came after the on click which mean if users click submit in the middle of editing a field, it fnck up.

@knilink thanks for the code snippet! It works like a charm.

In my scenario I blocks form submission and force the users to fix their input before submit. Validating when blur event is fired would help users visualizing their progress in fixing inputs.

I agree that on blur is unreliable. Therefore, I would like to validate both on submit and on blur, to strike a balance between user experience and reliability.

@knilink thanks for the snippet! but it validates all fields (even the untouched ones) when blur event is triggered. Is it possible to perform onBlur validation per field?

At present, react-jsonschema-form doesn't attempt to validate any user input at anything less than "the entire form" level.

Why was this closed? This should be kept open and a prop should be added to the <Form> so that this feature can be toggled, just like liveValidate. Validating on blur is a very common case.

I was able to implement this using a combination of liveValidate on the form and a few higher order components to manually track blurred state and show errors only once a field has been blurred on my custom widgets.

Here's what that could look like:

import {
  compose,
  mapProps,
  withStateHandlers,
} from "recompose";

const rawErrorsToErrorMessage = mapProps(
  ({ rawErrors, isBlurred, ...props }) => ({
    ...props,
    // TODO: Also need to show all errors after first submit
    errorMessage: isBlurred && rawErrors && (
      <React.Fragment>
        {rawErrors.map((error) => (
          <div>{error}</div>
        ))}
      </React.Fragment>
    ),
  }),
);

const withBlurred = withStateHandlers(
  { isBlurred: false },
  {
    onBlur: () => () => ({
      isBlurred: true,
    }),
  },
);

const transformWidgetProps = compose(
  withBlurred,
  rawErrorsToErrorMessage,
);

const widgets: any = {
  text: transformWidgetProps(TextInput),
  select: transformWidgetProps(OptionInput),
};

Hope this could be useful to others here.

UPDATE: Never mind, I later ran into a brick wall trying to show errors after the first submit attempt by wrapping a state tracking HOC around the form. For some reason, when the form gets rerendered, inputs lose their focus.

Create an example for selective field level onBlur validation.
https://codesandbox.io/s/blur-validation-react-json-schema-form-txnk8
Just provide 'validateOnBlur' true, in the uiSchema for that field, and it will do the job.

Hope it helps anyone facing this issue !

hope this help issue: 431

@KKS1 Thank you for putting together a proof of concept! I'm trying to get your example to work with material-ui and running into a problem. Since you're extending the Form, it requires:
import Form from '@rjsf/core';

and when I try this:

import { withTheme } from '@rjsf/core';
import { Theme as MaterialUITheme } from '@rjsf/material-ui';
const Form = withTheme(MaterialUITheme);

I get an error Uncaught TypeError: Class extends value #<Object> is not a constructor or null

How do I get onblur validation to work with Material UI? Any help would be greatly appreciated.

Did it work with import Form from '@rjsf/material-ui';

@epicfaace No, same error.

@stvhanna Created an end-to-end Material UI based implementation, using function based approach.
https://codesandbox.io/s/material-ui-blur-validation-react-json-schema-form-j4bms

Of-course, we can further optimize it using one time run effect, which can then call referenced Form onBlur if needed.
But this will give you ( or anyone else facing this issue) a base to start working with and make it production ready.

Hope it helps, cheers!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

norim13 picture norim13  路  3Comments

j-zimnowoda picture j-zimnowoda  路  3Comments

videni picture videni  路  3Comments

jabaren picture jabaren  路  3Comments

sstarrAtmeta picture sstarrAtmeta  路  3Comments