Unlock seamless workflows and faster delivery with our latest releases โ€“ get the details

Adding custom validation rules based on another field in Sanity.io

11 replies
Last updated: May 10, 2024
Hi everyone,
I'm just wondering how can I add some custom validation rules based on another field.

So say I have X set in one field and I want to make U field required how could I achieve this with the rule.custom function from the validation property
May 10, 2024, 4:44 PM
This is what i've tried so far with no luck, what is the validation rule expecting to return ?

validation: (rule) =>

rule.custom((value, context) => {

console.log("validation value", value);

console.log("context", context?.parent?.types ?? []);


if (

context?.parent?.types?.includes(SERVICE_PROVIDER_TYPE.HEALTHCARE_PROVIDER) &&

(value?.length ?? 0) === 0

) {

return rule.required();

}


return false;

}),
May 10, 2024, 4:47 PM
Regarding the return type this is what the docs say:
Sometimes you will need to validate values beyond what Sanity provides. The custom() method allows you to do this. It takes a function as the first argument, which should return either true (in the case of a valid value) or an error message as a string (in the case of an invalid value).
May 10, 2024, 5:54 PM
btw I think you can write
(value?.length ?? 0) === 0
as
!value?.length
as well
May 10, 2024, 5:55 PM
Hope that helps
May 10, 2024, 5:56 PM
Ah my bad I've completely missed that section, that makes more sense now thinking about it.
I ended up with something like this:


defineField({

name: "conditionTypes",

title: "Condition severity",

type: "array",

of: [{ type: "string" }],

validation: (rule) =>

rule.custom((value, context) => {

console.log("validation value", value);

console.log("types field value", context?.parent?.types ?? []);


if (context?.parent?.types?.includes(SERVICE_PROVIDER_TYPE.HEALTHCARE_PROVIDER) && !value?.length) {

return "Required";

}


return true;

}),

// If the "types" doesn't include the HEALTHCARE_PROVIDER value then hide this field, it's only applicable for service providers who offer HEALTHCARE_PROVIDER

hidden: ({ parent, value }) => !parent?.types?.includes(SERVICE_PROVIDER_TYPE.HEALTHCARE_PROVIDER) ?? true,

options: {

list: CONDITION_SEVERITY_OPTIONS?.map((conditionSeverity) => ({

title: conditionSeverity.label,

value: conditionSeverity.value

}))

}

})
May 10, 2024, 6:19 PM
I guess if using rule.custom() you have to do all of the sanity checks yourself so you can't chain then together which probably makes sense in a way.
May 10, 2024, 6:32 PM
No you can chain them but not inside the custom function as far as I am aware.
May 10, 2024, 6:38 PM
Example from my own codebase:
validation: (rule: Rule) => [
    rule.required(),
    rule.custom(validateSlug),
    rule.custom(maxLengthSlug(60)).warning(),
]
May 10, 2024, 6:38 PM
Ah cool that seems cool, what if one of those checks is condition if x is set make y required ? I take it you would just need to switch our required for a custom like you did for validating a slug.
May 10, 2024, 6:47 PM
Yes I think for that kind of logic you would need to go full custom and write your own implementation, for this example required goes first as the other validations donโ€™t have to run with 0 input.
May 10, 2024, 7:05 PM
Coolio. Appreciate the responses ๐Ÿ˜„ All makes sense now ๐Ÿ‘
May 10, 2024, 7:06 PM

Sanityโ€“ build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?