Search code examples
reactjsvalidationyup

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


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.


Solution

  • @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.