Search code examples
reactjstypescriptantd

How to correctly validate and submit if form is valid with ant design form with typescript


I build a simple form with react, redux, typescript ant design. Following the ant design documentation, I created a small form using the provided getFieldDecorator and Form.createmethods. Everything works fine so far and validation is handled by ant design itself when entering data into the fields. My main issue is with the form submit. I want to submit data only if the form is validated and the form is, therefore "valid".

The official documentation uses validateFields to validate the form and returns a variable which contains the errors and returns further execution so that the form doesn't get submitted. Now with typescript I have the following signatures: validateFields(): void; <- I use this method to trigger validation upon submit of the form and afterwards call getFieldsError(names?: Array<string>): Record<string, string[] | undefined>;

Now if you look at the example code, the ugly part is using a variable "allValid" to check if the form is valid or not. I thought there must be a simpler way of validating and submitting data if the form is valid.

const UploadForm: FunctionComponent<FormComponentProps> = props => {
  const { getFieldDecorator, validateFields, getFieldsError } = props.form;
  const dispatch = useDispatch();

  return (
    <Form
      {...formItemLayout}
      onSubmit={event => {
        event.preventDefault();
        validateFields();
        const validationErrors = getFieldsError();
        let allValid = true;
        console.log(validationErrors);
        for (let key in validationErrors) {
          console.log(validationErrors[key]);
          if (validationErrors[key] !== undefined) {
            allValid = false;
            break;
          }
        }

        if (allValid) {
          dispatch(submitFormData());
        }
      }}
    >
      <ImageComponent />
      <Form.Item label="E-mail">
        {getFieldDecorator("email", {
          rules: [
            {
              type: "email",
              message: "The input is not valid E-mail!"
            },
            {
              required: true,
              message: "Please enter your E-mail!"
            }
          ]
        })(
          <Input
            prefix={<Icon type="mail" style={{ color: "rgba(0,0,0,.25)" }} />}
            placeholder="Your e-mail"
          />
        )}
      </Form.Item>
      <Form.Item {...buttonItemLayout}>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

export default Form.create < FormComponentProps > {}(UploadForm);


Solution

  • You can use Object.values() and Array.find() to find the undefined value.

    validateFields();
    const validationErrors = Object.values(getFieldsError());
    
    if (!validationErrors.find(e => e === undefined)) dispatch(submitFormData());
    

    Or you can disable the submit Button.

    Validate each Form.Item, and allow submitting only when all validation status is success.

    <Button
      type="primary"
      htmlType="submit"
      disabled={!(validateEmptyField(name) && validateEmptyField(surName))}
    >
      Submit
    </Button>;
    
    

    Use validateStatus to validate each Form.Item:

    function FromValidate() {
      const [name, setName] = useState('');
      const [surName, setSurName] = useState('');
    
      return (
        <Flexbox>
          <Form
            onSubmit={e => {
              e.preventDefault();
              console.log('name', name);
              console.log('surName', surName);
            }}
          >
            <Form.Item
              label="Name"
              required={true}
              validateStatus={validateEmptyField(name) ? 'success' : 'error'}
              help={!validateEmptyField(name) && 'Name cannot be empty'}
            >
              <Input
                placeholder="Unique Identifier"
                value={name}
                onChange={e => setName(e.target.value)}
              />
            </Form.Item>
            ...
            <Form.Item>
              <Button
                type="primary"
                htmlType="submit"
                disabled={
                  !(validateEmptyField(name) && validateEmptyField(surName))
                }
              >
                Submit
              </Button>
            </Form.Item>
          </Form>
        </Flexbox>
      );
    }
    

    Edit Form-Validate