Nidhi Dadiya
Nidhi Dadiya

Reputation: 839

How to validate multiple emails using one validation schema field in Formik?

I have a customer form which takes two values.

  1. Customer name
  2. Customer Emails (Which can be multiples)

I've given an add button besides the email field through which user can add more emails to the form. now i want to validate each email that's been added. also if it's added it is required too. empty email is not allowed.

The question is i have only one validation schema to validate email field. how can i use the same field to validate multiple emails?

Even after adding the correct email. it still gives error !

Please see the sandbox link to see the code. code sandbox link

Upvotes: 1

Views: 5313

Answers (1)

Murli Prajapati
Murli Prajapati

Reputation: 9713

Here is the working code with multiple email validation and errors.
I've used Formik FieldArray to handle multiple emails.
You can replace your code with this in your sandbox to test.

import React from "react";
import { TextField, IconButton } from "@material-ui/core";
import {
  AddCircleOutlined as AddCircleOutlinedIcon,
  IndeterminateCheckBox as IndeterminateCheckBoxIcon
} from "@material-ui/icons";

//FORMIK
import { Formik, FieldArray, getIn, ErrorMessage } from "formik";
import * as Yup from "yup";

export default function UnitsDrawer(props) {
  const callAPI = e => {
    console.log(e.name);
    console.log(e.email);
  };

  const testSchema = Yup.object().shape({
    name: Yup.string().required("Customer name is required"),
    email: Yup.array().of(
      Yup.string()
        .email("Enter a valid email")
        .required("Email is required")
    )
  });

  const initialValues = {
    name: "",
    email: [""]
  };

  const formRef = React.useRef();

  return (
    <div>
      <Formik
        innerRef={formRef}
        validationSchema={testSchema}
        initialValues={initialValues}
        onSubmit={(values, actions) => {
          actions.setSubmitting(false);
          callAPI(values);
        }}
      >
        {({
          handleChange,
          handleBlur,
          values,
          errors,
          touched,
          handleSubmit,
          isSubmitting,
        }) => {
          return (
            <>
              <div>
                <TextField
                  label="Customer Name"
                  name="name"
                  margin="normal"
                  variant="outlined"
                  error={errors.name && touched.name}
                  onChange={handleChange}
                  onBlur={handleBlur}
                  value={values.name}
                  fullWidth
                />
                <ErrorMessage name="name" component="div" />
              </div>
              <FieldArray name="email">
                {({ push, remove }) =>
                  values.email.map((field, index) => (
                    <div key={`${index}`} className="dynamic-fields">
                      <div>
                        <TextField
                          label="Email"
                          variant="outlined"
                          className="input-item"
                          error={
                            getIn(touched, `email.${index}`) &&
                            getIn(errors, `email.${index}`)
                          }
                          name={`email.${index}`}
                          value={values.email[index]}
                          onChange={handleChange}
                          onBlur={handleBlur}
                          fullWidth
                        />
                        <ErrorMessage name={`email.${index}`} component="div" />
                      </div>
                      <IconButton
                        aria-label="filter list"
                        className="add-icon"
                        onClick={() => {
                          push("");
                        }}
                      >
                        <AddCircleOutlinedIcon color="primary" />
                      </IconButton>
                      {values.email.length > 1 && (
                        <IconButton
                          aria-label="filter list"
                          className="add-icon"
                          onClick={() => {
                            remove(index);
                          }}
                        >
                          <IndeterminateCheckBoxIcon />
                        </IconButton>
                      )}
                    </div>
                  ))
                }
              </FieldArray>
            </>
          );
        }}
      </Formik>
    </div>
  );
}

Upvotes: 1

Related Questions