yup.js Validate number field is larger than sibling, or nullable
Asked Answered
S

4

18

I'm using Yup.js to validate some form fields.

I have two integer fields, Year Built & Year Renovated.

Year Built is a required field, Year Renovated is not.

Year renovated can be left blank, however if there is a value it should be larger than year built (for a renovation certainly must occur after the date it was built).

I believe I need to use yup's ref() as well as yup's when() function. I've tried the following:

let currentYear = new Date().getFullYear();

yup.object().shape({
  yearBuilt     : yup.number().integer().min(1700).max(currentYear+1).required(),
  yearRenovated : yup.number().integer().when(
                    '$yearRenovated', (yearRenovated, schema)=>{
                        return yearRenovated > 0 ? 
                            schema.min(yup.ref('yearBuilt')).max(currentYear+1) :
                            schema.transform(emptyStringToNull).nullable()
                    }
                )
})

* The transform function, emptyStringToNull simply checks if value === '' and returns null if so.

The above does allow null values, as well as does correctly check for an integer. However it does not properly evaluate yearRenovated > yearBuilt. How do I properly check that if yearRenovated is not null, that it is greater than yearBuilt?

Thank you all so much for your help.

Stableman answered 7/5, 2020 at 15:29 Comment(0)
S
31

@JQuense, the owner of the repo had an eloquent solution, using moreThan():

const schema = yup.object().shape({
    yearBuilt: yup
      .number()
      .integer()
      .min(1700)
      .max(currentYear+1)
      .required(),
    yearRenovated: yup
      .number()
      .integer()
      .nullable()
      .moreThan(yup.ref("yearBuilt")) //<-- a whole lot neater than using a when conditional...
      .max(currentYear+1)
});

Hope that helps! Thank you @JQuense.

Stableman answered 8/5, 2020 at 15:3 Comment(3)
Really clean and easy way to check thanks @JQuenseDecern
I've to do a similar kinda thing. I have to compare two fields 'Min' and 'Max'. The problem is if I put any value in Min and doesn't touch the Max field. Even in that case error message is showing. I want these comparisons only if both the input box have values.Keelboat
@AnkitJaishwal - have you looked at using Schema.when(...)? You can have a conditional on when(myField.min(), myOtherFiled.max()) or something similar.Stableman
W
3
const schema = Yup.object({
  // -- snip --
  billAmount: Yup.number().nullable(),
  approvedAmount: Yup.number()
    .typeError("you must specify a number")
    .notRequired()
    .when("billAmount", (billAmount: any, schema: any) => {
      return schema.test({
        test: (approvedAmount: any) => {
          if (!approvedAmount) return true;
          return approvedAmount < billAmount;
        },
        message: "Approved Amount not gether then billAmount",
      });
    }),
});
Wanhsien answered 8/9, 2021 at 13:29 Comment(0)
V
0

Whenever You want to expecify a value from corrent key, just use the yup.ref("key"), in this way you can use this to create better conditions in yup validation schema!

Viridescent answered 22/2 at 15:27 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Wingover
T
-1

Yup (Less than or Equal To): https://github.com/jquense/yup/issues/538#issuecomment-495340254

If you end up needing a less than or equal to implementation (<=) consider this:

number().max(5) // is <= 5
Triennium answered 12/10, 2021 at 5:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.