Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a custom schema validation using yup.addMethod() for country name and code?

I'm trying to add form validations using yup to a React form component using formik. My validation seems to work, but I find it too verbose.

Trying to use the .addMethod() function of yup, but getting stuck on the syntax or maybe this is overkill?

Summary: I would like to convert my validation into an actual method using yup.addMethod().

Actual validation:

import * as yup from 'yup'

const countryNameRegex = /[A-Za-z]/g;
const countryCodeRegex = /[a-zA-Z]{2,}/g;
const isRequired = 'Required Field'
const isCorrectFormat = 'The country name may contain only letters'

const countryValidationSchema = yup.object().shape({
  name: yup.string()
    .min(3, `country name must contain at least 3 characters`)
    .matches(
      countryNameRegex,
      {
        message: isCorrectFormat,
        excludeEmptyStrings: true
      }
    )
    .label(`Country Name`)
    .required(isRequired),
  code: yup.string()
    .length(2, `The country code must be exactly 2 letters`)
    .matches(
      countryCodeRegex,
      { 
        message: isCorrectFormat,
        excludeEmptyStrings: true
      }
    )
    .label('Country Code')
    .required(isRequired),
});

export default countryValidationSchema;

My tryout using the yup.addMethod()

function isValidCountryName(ref, msg) {
  return yup.mixed().test({
    name: 'isValidCountry',
    exclusive: false,
    message: msg || `${ref.path} must be a valid country name`,
    params: {
      reference: ref.path,
    },
    test(value) {
     const isRightFormat = this.resolve(ref);
     return isRightFormat; [//ASK] should be doing the checks or transformations here
    },
  });
}

yup.addMethod(yup.string, 'isValidCountryName', isValidCountryName)
like image 629
intercoder Avatar asked Mar 04 '20 11:03

intercoder


People also ask

How do you validate two fields that depend on each other with Yup?

Solution: const yup = require('yup') const { setLocale } = yup setLocale({ mixed: { notType: 'the ${path} is obligatory', required: 'the field ${path} is obligatory', oneOf: 'the field ${path} must have one of the following values: ${values}' } }) const myNameSchema = yup. object(). shape({ first_name: yup.


1 Answers

You have 2 ways to do that:

  1. Using yup's built-in methods:
// Using built-in methods
function isValidCountry1() {
  return this.min(3, TOO_SMALL_ERROR_MESSAGE)
    .matches(COUNTRY_NAME_REGEX, {
      message: INVALID_FORMAT_ERROR_MESSAGE,
      excludeEmptyStrings: true
    })
    .required(REQUIRED_ERROR_MESSAGE);
}
yup.addMethod(yup.string, "isValidCountry1", isValidCountry1);
  1. Using custom test function:
// Using custom test method
function isValidCountry2(message) {
  return this.test("isValidCountry", message, function (value) {
    const { path, createError } = this;

    if (!value) {
      return createError({ path, message: message ?? REQUIRED_ERROR_MESSAGE });
    }

    if (value.length < 3) {
      return createError({ path, message: message ?? TOO_SMALL_ERROR_MESSAGE });
    }

    if (!value.match(COUNTRY_NAME_REGEX)) {
      return createError({
        path,
        message: message ?? INVALID_FORMAT_ERROR_MESSAGE
      });
    }

    return true;
  });
}
yup.addMethod(yup.mixed, "isValidCountry2", isValidCountry2);

After you've added the methods you can use them inside your validation schema:


const validationSchema = yup.object().shape({
  country1: yup.string().isValidCountry1(),
  country2: yup.mixed().isValidCountry2(),
  country3: yup.mixed().isValidCountry2("Country format is invalid.")
});

Here is the DEMO.

like image 117
teimurjan Avatar answered Oct 20 '22 22:10

teimurjan