Formsy-material-ui do not validate initial render

574 Views Asked by At

Is there any way, one can delay first validation of components in formsy-material-ui so that validations like isNotEmpty do not fire on first render of the form and mess the UX? I am using controlled components, therefore setting value from state on each render.

<FormsyText
    name="name"
    value={this.state.name}
    floatingLabelText="Name"
    onChange={partial(this._changeInputValue, ['name'])}
    validations={{ isNotEmpty }}
    validationError="Field shoud not be empty"
/>
1

There are 1 best solutions below

0
Faluvegi Ferenc On

I needed this solution too. I've been looking into the source code of formsy-material-ui, and it seems that the text field is setting its value right before it's mounted. That's why the field is marked changed (aka not pristine) when the rendering happens, so the validation error is shown.

Anyways, I wrote a hackish solution using a higher order component. I've been testing with text fields only, but should work with any fields having this problem. The core concept: if the formsy field doesn't have a "validationErrors" prop, it's not showing any errors.

import React, { Component, PropTypes } from 'react';

export const preventFirstValidation = (FormsyField) => {
  return class extends Component {
    static propTypes = { preventFirstValidation: PropTypes.bool };
    static defaultProps = { preventFirstValidation: true };

    constructor(props) {
      super(props);
      this.state = { isChanged: false };
    }

    render() {
      const { preventFirstValidation, ...fieldProps } = this.props;
      return (
        <FormsyField
          {...fieldProps}
          onChange={(evt, val) => {
            if (!this.state.isChanged) this.setState({ isChanged: true });
            if (this.props.onChange) this.props.onChange(evt, val);
          }}
          validationErrors={(this.state.isChanged || !preventFirstValidation) ? this.props.validationErrors : undefined}
        />
      );
    }
  };
};

How to use it:

import { Form } from 'formsy-react';
import FormsyTextField from 'formsy-material-ui/lib/FormsyText';

const TextField = preventFirstValidation(FormsyTextField);

const MyForm = () => (
  <Form>
    {/* You're using the transformed field, exactly like before */}
    <TextField
      name = "some_field"
      validationErrors={{ isRequired: 'This is really required!' }}
      required
      preventFirstValidation={ /* you can enable or disable this feature */ }
    />
  </Form>
);