javascriptreact-reduxredux-form

Redux Form: Conditional form validations with multiple submit buttons


enter image description here

I am using Redux forms with multiple submit buttons along with redux-form <Field />. I need to control the validation of these fields based on click of these buttons. For ex. I need to set a flag to True/False based on click of these buttons so that I can conditionally validate my fields like below:

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

As you can see from above code, I'm conditionally validating my fields with validate={isSaveDraft && [validateRequiredText]} and validate={!isSaveDraft && [validateRequiredText]}

Here are my two submit buttons:

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

However, I'm not able to achieve it. Please help.


Solution

  • After a lot of headaches and head scratching, I've finally found the solution without making things look ugly. Thanks to a fellow developer for this solution. Original idea was to set a flag on click of the button and conditionally validate the fields. (PS: I'm using Field Level Validations). However, the issue was that the validations are being executed BEFORE the flag setting as the onClick handler wouldn't fire before all the validations are fixed and that logic is buried deep inside redux-forms (perks of unnecessarily overcomplicating simple things by using a library).

    Here is the solution:

    submit handler

    handleSubmit() {
        const { bookingCreate, modalShow, navigateTo } = this.props;
        const { isDraftAction } = this.state; // my flag
    
        // create record!
        return bookingCreate(isDraftAction)
          .then(responsePayload => {
            ...
          })
          .catch(handleSubmissionError);
     }
    

    isDraftAction is the flag which is set (in local state) when the action is called on onClick of both buttons.

    My conditional Field level validations

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

    My 2 buttons for SAVE RECORD and 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() is my action function which will FIRST set the flag to true/false THEN call redux-forms inbuilt submit handler. Also, I've extracted the redux-form's submit handler as it is above only for more clarity.

    dispatchAction()

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