Redux 表单:具有多个提交按钮的条件表单验证

Redux Form: Conditional form validations with multiple submit buttons

我正在使用带有多个提交按钮的 Redux 表单以及 redux-form <Field />。我需要根据这些按钮的点击来控制这些字段的验证。对于前。我需要根据点击这些按钮将标志设置为 True/False,以便我可以有条件地验证我的字段,如下所示:

        <Field
          name="date"
          component={DateFormField}
          validate={isSaveDraft && [validateRequiredText]}
          floatingLabelText="Date"
          fullWidth
          helpText="blablabla"
        />
        <Field
          name="title"
          component={TextFormField}
          normalizeOnBlur={normalizeTextOnBlur}
          validate={!isSaveDraft && [validateRequiredText]}
          floatingLabelText="Project title"
          fullWidth
          helpText="blablabla"
        />

正如您从上面的代码中看到的,我正在使用 validate={isSaveDraft && [validateRequiredText]}validate={! isSaveDraft && [validateRequiredText]}

这是我的两个提交按钮:

      <RaisedButton
        label={submitting ? 'Saving Draft...' : 'Save Draft'}
        type="button"
        onClick={handleSubmit(values => onSubmit())}
        disabled={submitting}
        primary
      />
    <RaisedButton
      label={submitting ? 'Submitting Brief...' : 'Submit Brief'}
      type="button"
      onClick={handleSubmit(values => onSubmit())}
      disabled={submitting}
      primary
    />

但是,我无法实现它。请帮忙。

将状态变量用作 isSaveDraft 并将其默认设置为 false 添加按钮的 onClick 动作以设置 state.isSaveDraft = true

validate={(isSaveDraft && [validateRequiredText]} 将不起作用,因为 validate 一直需要一个函数。此外,字段级验证发生在 Touch 或 onBlur 等上。这太早了,因为您不知道将单击哪个按钮。

您需要做的是使用一个额外的标志属性来保存单击了哪个按钮,然后在表单级别验证中使用它。

因此您的字段将如下所示(不再进行字段级别验证):

<Field
    name="date"
    component={DateFormField}
    floatingLabelText="Date"
    fullWidth
    helpText="blablabla"
/>
...
<RaisedButton
    label={submitting ? 'Saving Draft...' : 'Save Draft'}
    onMouseDown={() => this.setDraftFlag(true)}        
    ...
/>
<RaisedButton
    label={submitting ? 'Submitting Brief...' : 'Submit Brief'}
    onMouseDown={() => this.setDraftFlag(false)}        
    ...
/>

我正在使用 onMouseDown 来捕获标志,因为您已经在使用 onClick 来提交表单。此外,无论如何我们都需要在提交之前进行验证。

然后在您的表单中 validate(基于 SyncValidation example

const validate = values => {
    const errors = {}
    const {isDraft, ...rest} = values

    if(isDraft) {
        // draft validations
    } else {
        // other validations
    }
    return errors
}

export default reduxForm({
    form: 'myForm', // a unique identifier for this form
    validate, // <--- validation function given to redux-form
})(MyForm)

setDraftFlag 可以是一个 action 或者你可以像这样让它成为你的表单组件的一部分(我发现这更容易,因为你已经将 change 绑定到你的表单):

setDraftFlag(value) {
    this.props.change('isDraft', value));
}

经过大量的头痛和挠头之后,我终于找到了解决方案,而且不会让事情变得难看。感谢此解决方案的开发人员。最初的想法是在单击按钮时设置一个标志并有条件地验证字段。 (PS:我正在使用字段级验证)。然而,问题是验证是在标志设置之前执行的,因为在修复所有验证之前不会触发 onClick 处理程序,并且该逻辑深埋在 redux-forms 中(通过使用库使简单的事情不必要地过度复杂化的好处) ).

解决方法如下:

提交处理程序

handleSubmit() {
    const { bookingCreate, modalShow, navigateTo } = this.props;
    const { isDraftAction } = this.state; // my flag

    // create record!
    return bookingCreate(isDraftAction)
      .then(responsePayload => {
        ...
      })
      .catch(handleSubmissionError);
 }

isDraftAction 是在两个按钮的 onClick 上调用操作时设置 (in local state) 的标志。

我的条件字段级别验证

    <Field
      name="date"
      component={DateFormField}
      validate={isDraftAction && [validateRequiredText]}
      fullWidth
      helpText="blablabla"
    />
    <Field
      name="title"
      component={TextFormField}
      normalizeOnBlur={normalizeTextOnBlur}
      validate={!isDraftAction && [validateRequiredText]}
      fullWidth
      helpText="blablabla"
    />

我的 SAVE RECORD 和 SUBMIT RECORD 两个按钮。

  const submit = handleSubmit(values => onSubmit()); // this is redux-form's submit handler which will in-turn call my own submit handler defined above. (That's where the library hides all the logic and makes developer helpless)

  <RaisedButton
    label={submitting && isDraft ? 'Saving Draft...' : 'Save Draft'}
    type="button"
    onClick={() => {
      this.props.dispatchAction({ draftAction: true }).then(() => {
        submit();
      });
    }}
    disabled={submitting}
    primary
  />
  <RaisedButton
    label={submitting && !isDraft ? 'Submitting Brief...' : 'Submit Brief'}
    type="button"
    onClick={() => {
      this.props.dispatchAction({ draftAction: false }).then(() => {
        submit();
      });
    }}
    disabled={submitting}
    primary
  />

dispatchAction() 是我的操作函数,它将首先将标志设置为 true/false 然后调用 redux-forms 内置提交处理程序。此外,我已经提取了 redux-form 的提交处理程序,因为它只是为了更清楚。

dispatchAction()

     dispatchAction={({ draftAction }) =>
        new Promise(resolve => {
          this.setState({ isDraftAction: draftAction }, resolve);
        })
      }