Search code examples
redux-form

How to submit invalid form in redux-form? And is it even possible?


I have a form and 2 submit flows: draft and detailed.

There is no validation for submitting the draft.

Some of the fields are required for detailed submitting. One of them is "description".

Invalid form:

invalid form

Valid form:

valid form Validation works properly and "description" field gets marked as "invalid" if empty:

<Field
  component="textarea"
  name="description"
  maxLength={2048}
  validate={[required()]}
  label={<FormattedMessage id={messageIds['entity.ticket.field.description']} />}
/>

But at the same time, I can't submit this form as "draft" when the description is empty.

Shortened code:

function TicketFormComponent(props: AllProps) {
  const handleDraftTicketSubmit = props.handleSubmit((values) => {
    props.onTicketCreate({
      ...values,
      status: 'Draft',
    });
  });

  const handleActiveTicketSubmit = props.handleSubmit((values) => {
    props.onTicketCreate({
      ...values,
      status: 'Open',
    });
  });

  return (
    <Form onSubmit={handleActiveTicketSubmit}>
      <Field
        component={TextInput}
        name="subject"
        maxLength={255}
        label={<FormattedMessage id={messageIds['entity.ticket.field.subject']} />}
      />

      <h3><FormattedMessage id={messageIds['entity.ticket.field.description']} /></h3>
      <Field
        component="textarea"
        name="description"
        maxLength={2048}
        validate={[required()]}
        label={<FormattedMessage id={messageIds['entity.ticket.field.description']} />}
      />

      <Button
        data-aqa="submitDraftTicket"
        disabled={props.submitting || !props.initialValues.selectedTopic}
        onClick={handleDraftTicketSubmit}
        className={props.classes.saveDraftButton}
      >
        <FormattedMessage id={messageIds['entity.ticket.field.saveAsDraft']} />
      </Button>

      <Button
        data-aqa="submitActiveTicket"
        disabled={props.submitting || props.invalid}
        onClick={handleActiveTicketSubmit}
        variant="contained"
        color="primary"
      >
        <FormattedMessage id={messageIds['entity.ticket.field.createNewTicket']} />
      </Button>
    </Form>
  );
}

Expected result:

Form values are submitted with "Draft" status further through Redux flow

Actual result:

form values are not submitted, instead, I get 2 redux actions:

  1. { type: '@@redux-form/TOUCH' }
  2. { type: '@@redux-form/SET_SUBMIT_FAILED', error: true }

Solution

  • I'm seeing two possibles approaches:

    1. Remove Field level validation (validate={[required()]}) and validate the Form with SyncValidation:

    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)
    

    2. Add the Field validation conditionally:

    <Field
      name="description"
      validate={!isDraft && [required()]}
    />
    

    But here you should change your submission flow. Rather than submitting the Form on 'Save draft' or 'Create ticket' buttons, you have to set a state isDraft variable firstly and later submit the form.

    Otherwise, submitting the Form on a button click, the conditional Field validation won't be applied, because the Form will be already submitted.


    Here, the use-case is very similar to yours. So you can take inspiration of it too.