javascript - Using Joi andor Yup for schema validation, is there a way to make a collection of properties required if any of the

Take for example an HTML form that collects the details of a person.Note: Code snippets are simplified

Take for example an HTML form that collects the details of a person.

Note: Code snippets are simplified and do not match up with the screenshot exactly. Also, code snippets are written using Yup, which is a very similar library to Joi that targets the browser rather than NodeJS.

In order to submit the form, I want to run validations on the address fields and make them required, but only if the user has partially filled out the address section. As a whole, I want to make the address details optional.

Here is a simplified version of my PersonSchema...

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

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

Defining AddressSchema in this way does not work because the fields are always required...

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()
})

And here was my attempt to make address fields dependent on the presence of other address fields, but this does not work because you run into circular dependency issues...

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()
    })
})

Take for example an HTML form that collects the details of a person.

Note: Code snippets are simplified and do not match up with the screenshot exactly. Also, code snippets are written using Yup, which is a very similar library to Joi that targets the browser rather than NodeJS.

In order to submit the form, I want to run validations on the address fields and make them required, but only if the user has partially filled out the address section. As a whole, I want to make the address details optional.

Here is a simplified version of my PersonSchema...

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

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

Defining AddressSchema in this way does not work because the fields are always required...

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()
})

And here was my attempt to make address fields dependent on the presence of other address fields, but this does not work because you run into circular dependency issues...

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()
    })
})
Share Improve this question asked May 14, 2019 at 17:29 J. MunsonJ. Munson 2,9053 gold badges21 silver badges24 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

I needed the same optional address check: Rather than checking each field based against every other address field, just set a flag in your form/schema named something like 'addressStarted', then use that as your when trigger. The flag was an explicit choice by the user in my case, but it could just as easily be a hidden value; just toggle the value to true in every onChange handler (if you're using something like Formik), or even just an event listener on an element that contains all the address fields.

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()
  }),
})

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744834587a4596187.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信