无法仅通过 Formik 获取验证以触发 Antd 表单 - 错误字段仅在实际尝试提交时显示

Cannot get validation only to fire for Antd form with Formik - errored fields only show when actually trying to submit

我无法通过单击按钮而不是提交来仅验证(不提交)我的表单(Antd 表单)。让它验证和更新错误字段的唯一方法是我尝试提交它。有没有办法做到这一点?还是我必须提交表格?

我有一个用于提交的按钮和一个仅用于验证的按钮 - 仅验证按钮调用 validateForm 方法,但表单上没有任何更新。

编辑这里有一个 link 到 codesandbox 来演示这个https://codesandbox.io/s/xo5ln7l32p ...再次 -当我触摸文本框或单击提交按钮时,验证工作并在文本框下方显示错误消息,但是,当单独单击“全部验证”时,文本框下方没有显示错误。

这是我的基本 Antd 表单的代码:

import React from 'react';
import PropTypes from 'prop-types';
import { Form as AntdForm } from 'antd';
import FormValidationAlert from './FormValidationAlert';

function Form({ children, onSubmit, isValid, validationErrors }) {
  return (
    <AntdForm layout="vertical" onSubmit={onSubmit} style={{ margin: 20 }}>
      {!isValid && <FormValidationAlert validationErrors={validationErrors} />}
      {children}
    </AntdForm>
  );
}

Form.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  isValid: PropTypes.bool.isRequired,
  validationErrors: PropTypes.array
};

export default Form;

这是我的表格:

import React from 'react';
import PropTypes from 'prop-types';
import { Formik } from 'formik';
import * as Yup from 'yup';
import { Col, Row, Steps } from 'antd';
import {
  Form,
  TextInput
} from '../common/forms';

class CreateItemForm extends React.Component {
  render() {
    const formik = {
      initialValues: {
        name: ''
      },
      validationSchema: Yup.object().shape({
        name: Yup.string().required('Name is required.')
      }),
      onSubmit: (values, actions) => {
        this.props.onSubmit(values);
      }
    };

    console.log('this.props', this.props);

    const { setFormRef, status, currentStep } = this.props;

    return (
      <Formik
        ref={setFormRef}
        {...formik}
        render={form => (
          <Form
            onSubmit={form.handleSubmit}
            isValid={status.isValid}
            validationErrors={status.validationErrors}
          >
            <TextInput
              {...form}
              name="name"
              placeholder="Name"
              label="Name"
            />
            <button type="button" onClick={() => validateForm().then(() => console.log(blah))}>
              Validate All
                    </button>
            <button type="submit">Submit</button>
          </ Form>
        )}
      />
    );
  }
}

CreateItemForm.propTypes = {
  onSubmit: PropTypes.func.isRequired,
  status: PropTypes.object.isRequired,
  setFormRef: PropTypes.func.isRequired
};

export default CreateItemForm;

这是我的 TextInput:

import React from 'react';
import PropTypes from 'prop-types';
import { Form, Input } from 'antd';
import ReactInputMask from 'react-input-mask';

function TextInput({
  values,
  errors,
  touched,
  handleSubmit,
  setFieldValue,
  setFieldTouched,
  name,
  label,
  placeholder,
  disabled,
  addOnBeforeValue,
  addOnAfterValue,
  mask,
  maskPermanents
}) {
  return (
    <Form.Item
      label={label}
      hasFeedback={!!errors[name]}
      validateStatus={touched[name] && errors[name] && 'error'}
      help={touched[name] && errors[name]}
    >
      {mask ? (
        <ReactInputMask
          disabled={
            disabled === null || disabled === undefined ? false : disabled
          }
          alwaysShowMask={false}
          value={values[name]}
          onChange={event => setFieldValue(name, event.target.value)}
          onBlur={() => setFieldTouched(name)}
          mask={mask}
          permanents={maskPermanents}
        >
          {inputProps => (
            <Input
              {...inputProps}
              placeholder={placeholder}
              onPressEnter={handleSubmit}
              addonBefore={addOnBeforeValue}
              addonAfter={addOnAfterValue}
            />
          )}
        </ReactInputMask>
      ) : (
          <Input
            disabled={disabled}
            placeholder={placeholder}
            value={values[name]}
            onChange={event => setFieldValue(name, event.target.value)}
            onBlur={() => setFieldTouched(name)}
            onPressEnter={handleSubmit}
            addonBefore={addOnBeforeValue}
            addonAfter={addOnAfterValue}
          />
        )}
    </Form.Item>
  );
}

TextInput.propTypes = {
  values: PropTypes.object,
  errors: PropTypes.object,
  touched: PropTypes.object,
  handleSubmit: PropTypes.func,
  setFieldValue: PropTypes.func,
  setFieldTouched: PropTypes.func,
  name: PropTypes.string.isRequired,
  label: PropTypes.string,
  disabled: PropTypes.bool,
  placeholder: PropTypes.string,
  addOnBeforeValue: PropTypes.string,
  addOnAfterValue: PropTypes.string,
  mask: PropTypes.string,
  maskPermanents: PropTypes.arrayOf(PropTypes.number)
};

export default TextInput;

是的,您可以验证按钮点击而不是表单提交。 您应该考虑的几点。

  1. 您应该用标签包裹表单元素。
  2. 不要忘记使用导出方法 wrap with create form 方法。

    export default Form.create()(SimpleForm);

  3. 添加一个 onlick 方法并使用如下验证方法。

    this.props.form.validateFieldsAndScroll((错误, 值) => { 如果(!错误){ //做你想做的事。 } });

  4. 对字段使用正确的验证方法

祝你好运!

在验证所有按钮点击时,您可以使用 form.submitForm();

您可以在此处查看工作中的 stackblitz 演示。

代码片段

function doSave(values) {
  console.log("saving data", values);
}

function validateAllClick(form) {
  form.submitForm();
  console.log("just validating");
}


function App() {
  return (
    <Layout>
      <h1>Here's My Form</h1>
      <Content>
        <CreateItemForm
          status={editModelStatus}
          setFormRef={setFormRef}
          onSubmit={values => doSave(values)}
          onValidate={validateAllClick}
        />
      </Content>
    </Layout>
  );
}

我想通了 - 它没有显示错误,因为 TextInput 中的 Form.Item 正在检查要首先触摸的字段:

<Form.Item
      label={label}
      hasFeedback={!!errors[name]}
      validateStatus={touched[name] && errors[name] && 'error'}
      help={touched[name] && errors[name]}
>

...将其更改为以下内容可以使它起作用(我只是删除了是否实际触摸了该字段的检查):

<Form.Item
      label={label}
      hasFeedback={!!errors[name]}
      validateStatus={errors[name] && 'error'}
      help={errors[name]}
>