Dynamic array max validation based on dropdown selection in Sanity

4 replies
Last updated: Dec 9, 2021
Hey Everyone 🙂I am having some trouble with custom validation of an array. What I am trying to achieve is to change the "Rule.max()" based on the selection of a dropdown list. I am struggling to wrap my head around the controls of validation rules outside of "required". I have attached where I am currently at, which obviously doesn't work because the custom rule needs to return a bool.

If anyone could please guide me in the right direction for this custom validation that would be amazing
🙂
AI Update

Based on your question, you're looking to create a custom validation rule for an array where the max length changes based on another field's value (like a dropdown). The key insight is that custom validation functions should return true when valid, or an error string/object when invalid - not a boolean for the invalid case.

Here's how to implement conditional array validation based on another field:

defineField({
  name: 'myArray',
  type: 'array',
  of: [{ type: 'string' }],
  validation: (rule) =>
    rule.custom((value, context) => {
      // Access the parent document to get the dropdown value
      const selectedOption = context?.parent?.myDropdown;
      
      // Define your max lengths based on dropdown selection
      let maxLength;
      switch (selectedOption) {
        case 'option1':
          maxLength = 3;
          break;
        case 'option2':
          maxLength = 5;
          break;
        case 'option3':
          maxLength = 10;
          break;
        default:
          maxLength = 5; // default max
      }
      
      // Check if array exceeds the conditional max
      if (value && value.length > maxLength) {
        return `Maximum ${maxLength} items allowed for ${selectedOption}`;
      }
      
      // Return true if validation passes
      return true;
    }),
})

The critical points here:

  1. Use rule.custom() instead of trying to dynamically chain .max() - custom validation gives you full control
  2. Access context: Use context?.parent to read other fields in the same document (like your dropdown)
  3. Return values: Return true when valid, or return an error string when invalid (not false)
  4. Handle undefined: Check if value exists before checking its length to avoid errors

You can also add this as an additional validation alongside other rules:

validation: (rule) => [
  rule.required(),
  rule.custom((value, context) => {
    // your conditional logic here
  })
]

The official validation documentation has more examples, and there's a helpful answer about conditional validation based on other fields that shows similar patterns.

Show original thread
4 replies
Hey Geoff! Ohh of course, so you still make it a Boolean value and just provide the context within the error message itself. Thank you so much! I was tunnel visioning on that one too much
You’ve got it! Rule.custom() wants to return either true or an error message. A switch might be handy if the conditions get numerous, but tomorrow I’ll take a look at your max approach as there may be an interesting way to handle it that way, too.
Beauty that's working nicely 🙂 The fields I am working on are nested a wee bit of a way down a doc so I switch to context.parent and it came together.
Ok awesome 🙂 Curious to see if you come up with something. Thanks again for your help Geoff

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?