Skip to main content

Form validation

More often than not form fields require validation. We can add validation in formik with Yup.

Basic example#

import { useIntl } from 'react-intl';import * as yup from 'yup';
export const usePaymentMethodValidationSchema = () => {  const intl = useIntl();
  const validationSchema = yup.object().shape({    Name: yup      .string()      .required(intl.formatMessage({ id: 'generic.error.message.required' }))      .min(2)      .max(255),    Code: yup      .string()      .required(intl.formatMessage({ id: 'generic.error.message.required' }))      .min(2)      .max(255),  });
  return validationSchema;};

Nested objects#

const validationSchema = yup.object().shape({  ProductID: yup.number().required(intl.formatMessage({ id: 'generic.error.message.required' })),  Quantity: yup    .number()    .integer()    .positive()    .required(intl.formatMessage({ id: 'generic.error.message.required' })),  UnitPrice: yup    .number()    .required(intl.formatMessage({ id: 'generic.error.message.required' }))    .positive(intl.formatMessage({ id: 'generic.error.message.number.positive' }))    .min(0, (val) =>      intl.formatMessage({ id: 'generic.error.message.number.min' }, { min: val.min }),    ),});

Arrays#

const validationSchema = Yup.object().shape({    tiers: Yup.array()      .of(        Yup.object().shape({          ...        }),      )      .required(),

Specific value#

const validationSchema = yup.object().shape({  name: yup.string().required(    intl.formatMessage({      id: 'edit-discount.general-info.ou-details-dialog.tabs.create-ou-set.name.required',    }),  ),  includedOrganiationUnitSets: yup.array().min(    1,    intl.formatMessage({      id: 'edit-discount.general-info.ou-details-dialog.tabs.create-ou-set.included.required',    }),  ),  type: yup.number().oneOf([OrganizationUnitSetType.AdHoc, OrganizationUnitSetType.Custom]),});

Numbers#

const validationSchema = Yup.object().shape({  DiscountPercentage: Yup.number()    .required(intl.formatMessage({ id: 'generic.error.message.required' }))    .positive(intl.formatMessage({ id: 'generic.error.message.number.positive' }))    .max(100, ({ max }) => intl.formatMessage({ id: 'generic.error.message.number.max' }, { max }))    .min(0, ({ min }) => intl.formatMessage({ id: 'generic.error.message.number.min' }, { min })),});

Conditional validation based on other fields#

const validationSchema = Yup.object().shape({  percentageTiers: Yup.array().when(    'discountType',    (discountType: SlidingDiscountType, schema: any) =>      discountType === SlidingDiscountType.OrderTieredDiscountPercentage        ? schema.required().min(1)        : schema.nullable(),  ),  amountTiers: Yup.array().when('discountType', (discountType: SlidingDiscountType, schema: any) =>    discountType === SlidingDiscountType.OrderTieredDiscountAmount      ? schema.required().min(1)      : schema.nullable(),  ),  isProductSetValid: Yup.bool().when(    'discountFocus',    (discountFocus: SlidingDiscountFocus, schema: any) =>      discountFocus === SlidingDiscountFocus.ProductQuantity        ? schema.oneOf([true])        : schema.oneOf([true, false]),  ),});

Cyclic validation#

Sometimes there are fields that are co-dependent with regards to validation

const validationSchema = yup.object().shape(  {    Name: yup.string().required(      intl.formatMessage({        id: 'price-lists.details.general-info.name.required',      }),    ),    CurrencyID: yup.string().required(      intl.formatMessage({        id: 'price-lists.details.general-info.currency-id.required',      }),    ),    IncludingVat: yup.boolean().required(),    IsActive: yup.boolean().required(),    BackendID: yup.string().when('BackendSystemID', (backendSystemID: string, schema: any) =>      backendSystemID        ? schema.required(            intl.formatMessage({              id: 'price-lists.details.general-info.backend-id.required',            }),          )        : schema.nullable(),    ),    BackendSystemID: yup.string().when('BackendID', (backendId: string, schema: any) =>      backendId        ? schema.required(            intl.formatMessage({              id: 'price-lists.details.general-info.backend-system-id.required',            }),          )        : schema.nullable(),    ),  },  [['BackendID', 'BackendSystemID']],);