【问题标题】:Redux Form: Conditional form validations with multiple submit buttonsRedux Form:带有多个提交按钮的条件表单验证
【发布时间】:2018-10-10 04:35:42
【问题描述】:

我正在使用带有多个提交按钮的 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]} 有条件地验证我的字段/strong>

这是我的两个提交按钮:

      <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
    />

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

【问题讨论】:

    标签: javascript react-redux redux-form


    【解决方案1】:

    经过很多头痛和挠头后,我终于找到了解决方案,而不会让事情看起来很丑陋。感谢此解决方案的开发人员。最初的想法是在单击按钮时设置一个标志并有条件地验证字段。 (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"
        />
    

    我的 2 个按钮用于保存记录和提交记录。

      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);
            })
          }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 我的 onClick 函数在字段验证后触发。
      【解决方案3】:

      validate={(isSaveDraft &amp;&amp; [validateRequiredText]} 将无法工作,因为validate 始终需要一个函数。此外,字段级别的验证发生在 onTouch 或 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));
      }
      

      【讨论】:

      • validate={(isSaveDraft &amp;&amp; [validateRequiredText]} will not work since validate expects a function all the time. 这工作正常。 validateRequiredText 是一个函数,isSaveDraft 是一个布尔值。
      • I'm using onMouseDown... 如果用户使用键盘,这将失败。所以这将是一个可访问性问题。
      • 为键盘添加另一个处理程序。
      • 顺便说一句,onClick 也是一个鼠标事件。
      • 但是如果你问我,有 2 个按钮,而不是一个 submit 是一个糟糕的设计,如果你如此关心可访问性,那么这是一个糟糕的设计。我只需将“另存为草稿”更改为一个复选框,并且只有一个提交按钮。您的表单验证变得更简单,可访问性得分上升,每个人都赢了。
      猜你喜欢
      • 2014-12-11
      • 2017-04-12
      • 2013-03-17
      • 2017-05-09
      • 2012-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多