Используя Joi и / или Yup для проверки схемы, есть ли способ сделать набор свойств обязательным, если присутствуют какие-либо другие свойства? - PullRequest
0 голосов
/ 14 мая 2019

Возьмем, к примеру, форму HTML, в которой собраны данные о человеке.

sample form

Примечание. Фрагменты кода упрощены и не полностью соответствуют скриншоту. Кроме того, фрагменты кода пишутся с использованием Yup, очень похожей на библиотеку Joi, которая ориентирована на браузер, а не на NodeJS.

Чтобы отправить форму, я хочу выполнить проверки в полях адреса и сделать их обязательными, но только если пользователь частично заполнил раздел адреса. В целом, я хочу сделать детали адреса необязательными.

Вот упрощенная версия моей PersonSchema ...

import { object, string, number } from 'yup'

const PersonSchema = object().shape({
  name: string().required(),
  age: number()
    .positive()
    .integer()
    .required(),
  address: AddressSchema
})

Определение AddressSchema таким способом не работает, потому что поля всегда обязательны для заполнения ...

const AddressSchema = object().shape({
  street: string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required(),
  city: string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required(),
  state: string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required()
})

И здесь я попытался сделать поля адреса зависимыми от наличия других полей адреса, но это не работает, потому что вы сталкиваетесь с проблемами циклической зависимости ...

const AddressSchema = object().shape({
  street: string()
    .when(['city', 'state'], {
      is: (city, state) => city || state,
      then: string()
        .min(2, 'Too Short!')
        .max(50, 'Too Long!')
        .required(),
      otherwise: string()
    }),
  city: string()
    .when(['street', 'state'], {
      is: (street, state) => street || state,
      then: string()
        .min(2, 'Too Short!')
        .max(50, 'Too Long!')
        .required(),
      otherwise: string()
    }),
  state: string()
    .when(['street', 'city'], {
      is: (street, city) => street || city,
      then: string()
        .min(2, 'Too Short!')
        .max(50, 'Too Long!')
        .required(),
      otherwise: string()
    })
})

1 Ответ

1 голос
/ 30 мая 2019

Мне потребовалась та же дополнительная проверка адреса: вместо того, чтобы проверять каждое поле на основе любого другого поля адреса, просто установите флаг в вашей форме / схеме с именем что-то вроде 'addressStarted', а затем используйте его в качестве своего триггера когда.Флаг был явным выбором пользователя в моем случае, но он мог также легко быть скрытым значением;просто установите значение true в каждом обработчике onChange (если вы используете что-то вроде Formik) или даже просто прослушиватель событий для элемента, который содержит все поля адреса.

import { object, string, number } from 'yup'

const AddressSchema = object().shape({
  street: string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required(),
  city: string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required(),
  state: string()
    .min(2, 'Too Short!')
    .max(50, 'Too Long!')
    .required()
})

const PersonSchema = object().shape({
  name: string().required(),
  age: number()
    .positive()
    .integer()
    .required(),
  addressStarted: Yup.boolean(),
  address: object().when('addressStarted', {
    is: true,
    then: AddressSchema,
    otherwise: object().notRequired()
  }),
})

...