无法仅使用Formik的Antd表单触发验证-错误字段仅在实际尝试提交时显示

时间:2018-10-31 02:21:39

标签: reactjs antd formik

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

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

编辑这是到codeandbox的链接,以证明这一点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;

3 个答案:

答案 0 :(得分:1)

我发现了这一点-它没有显示错误,因为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]}
>

答案 1 :(得分:0)

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

  1. 您应使用标签包裹表单元素。
  2. 别忘了将导出方法wrap与create form方法一起使用。

    export default Form.create()(SimpleForm);

  3. 添加一个onlick方法并使用如下所示的validate方法。

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

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

祝你好运!

答案 2 :(得分:0)

在验证所有按钮单击后,您可以使用<Image AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds=".5,.5,150,150" />

您可以在此处查看stackblitz演示示例。

代码段

form.submitForm();