Search code examples
reactjsformikyup

Formik : Require validation only if the field is visible


I have a form including a checkbox which if it is true causes a new field to appear.

and I would like that when the field is visible it can be considered as Required and no required if it is invisible.

Here endComment should be required only when show is true

Would you have a solution ?

The global code :

 const Form = {
   const [show, setShow] = useState<boolean>(props.event.endDate ? true : false);
   const addEndComment = (value: boolean) => {
     setShow(value);
   };

const schema = yup.object().shape({
    comment: yup.string().required(),
    endComment: yup.string().required(),
});

    return (
        <>
            <Formik
                enableReinitialize
                initialValues={{
                    comment: props.event.comment,
                    endComment: props.event.endComment,
                }}
                onSubmit={(values) => {
                  ....
                }}
                validationSchema={schema}
            >
                {(formikProps) => (
                    <form onSubmit={formikProps.handleSubmit}>
                        <section>
                            <p>
                                <I18nWrapper
                                    translateKey={'event.form-create-event.explanations'}
                                />
                            </p>
                        </section>
                        <section>
                            <Form.Group controlId="eventComment">
                                <Form.Label>
                                    <I18nWrapper
                                        translateKey={'event.form-create-event.comment-label'}
                                    />
                                </Form.Label>
                                <Form.Control
                                    value={formikProps.values.comment || ''}
                                    onChange={formikProps.handleChange}
                                    as="textarea"
                                    rows={3}
                                    name="comment"
                                    isInvalid={!!formikProps.errors.comment}
                                />
                                <Form.Control.Feedback
                                    type="invalid"
                                    role="alert"
                                    aria-label="no comment"
                                >
                                    <FontAwesomeIcon icon={faTimes} className="me-2" size="lg"/>
                                    <I18nWrapper
                                        translateKey={'reminder.modal.phone-reminder.error'}
                                    />
                                </Form.Control.Feedback>
                            </Form.Group>
                        </section>
                        <section>
                            <SimpleGrid columns={columns} rows={rows}/>
                        </section>
                        <section>
                            <Form.Group controlId="formBasicCheckbox">
                                <Form.Check
                                    type="checkbox"
                                    label={t('event.form-resolve-event.checkbox-label')}
                                    checked={show}
                                    onChange={(e) => addEndComment(e.target.checked)}
                                />
                            </Form.Group>
                        </section>
                        {show ? (
                            <React.Fragment>
                                <section>
                                    <I18nWrapper
                                        translateKey={'event.form-resolve-event.comment-end-label'}
                                    />
                                    <Form.Control
                                        value={formikProps.values.endComment || ''}
                                        onChange={formikProps.handleChange}
                                        as="textarea"
                                        rows={3}
                                        name="endComment"
                                        isInvalid={!!formikProps.errors.endComment}
                                    />
                                    <Form.Control.Feedback
                                        type="invalid"
                                        role="alert"
                                        aria-label="no comment"
                                    >
                                        <FontAwesomeIcon
                                            icon={faTimes}
                                            className="me-2"
                                            size="lg"
                                        />
                                        <I18nWrapper
                                            translateKey={'reminder.modal.phone-reminder.error'}
                                        />
                                    </Form.Control.Feedback>
                                </section>
                            </React.Fragment>
                        ) : null}

                        <div className="text-center">
                            <GenericButton
                                label={'button'}
                                type="submit"
                                disabled={!formikProps.isValid}
                            />
                        </div>
                    </form>
                )}
            </Formik>
        </>
    );
};



export default Form;

Solution

  • You can simply change the schema based on the show state

    Example:

    const schema = yup.object().shape({
        comment: yup.string().required(),
        endComment: show ? yup.string().required() : yup.string(),
    });
    

    OR

    If you have the show state as a part of formik's state you can use formik's conditional validation, for example

    const schema = yup.object().shape({
        comment: yup.string().required(),
        endComment: Yup.string().when('show', {
        is: true,
        then: Yup.string().required()
      }),
    });
    

    Refer yup docs for more info