đź”® Sanity Create is here. Writing is reinvented. Try now, no developer setup

Help needed with building a nested category system in JavaScript

3 replies
Last updated: Feb 16, 2023
I know I've asked this before... but I can't find the answer anywhere, apologies.
In v2, when creating custom components, we could access the validation rules of a field to provide data back to the custom components. (see
here for v2 docs example)
Schema data example:

validation: Rule => Rule.max(100)

and in the custom component example:


import { TextInput, Stack, Text } from '@sanity/ui'

...

const MaxConstraint = type.validation[0]._rules.filter(rule => rule.flag == 'max')[0].constraint

const handleChange = React.useCallback(
  (event) => {
    const inputValue = event.currentTarget.value
      onChange(PatchEvent.from(inputValue ? set(inputValue) : unset()))
  },
  [onChange]
)

...

<Text muted size={1}>{value ? value.length : '0'} / {MaxConstraint}</Text>
Unfortunately, the v3 docs don't provide much insight into accessing the validation rules now. Any examples that someone could share?
Feb 10, 2023, 2:15 AM
I haven’t implemented them, but both
validation
and
validationError
are provided to a field component through
props
. Maybe try playing around with one of those?
Feb 10, 2023, 7:14 PM
For others who might be interested...

/ A function that returns only objects containing specified key/value pairs.
// Not all validation rules are required for this component.
// ! Be sure that your schema validation rules are concatenated `Rule.min(20).max(50)` and not passed as an array of rules `[Rule.min(20), Rule.max(50)]`

function findByKeyValue(array: any, key: any, value: any) {
  var result = array.find(function (obj: any) {
    return obj[key] === value;
  });
  return result || null;
}

export function CharacterCounterField(props: any) {

  // Assign our array for ease of use
  const rulesArray = props.schemaType.validation[0]._rules;
  // Get our min and max values from the validation rules
  const min = findByKeyValue(rulesArray, "flag", "min");
  const max = findByKeyValue(rulesArray, "flag", "max");
  
  // Set our colour based on the length of the value
  // @TODO Can this be logical query be improved?
  let myColour;
  max !== null &&
  props.value?.length < max.constraint &&
  min !== null &&
  props.value?.length > min.constraint
    ? (myColour = "green")
    : (myColour = "red");

  return (
    <Stack space={3}>
      {!-- @TODO Customise TextInput for green bg and borders when in range --}
      {props.renderDefault(props)}
      <Text
        size={1}
        style={{
          color: myColour,
        }}
      >
        Characters: {props.value?.length || 0}.
      </Text>
    </Stack>
  );
}
I'm sure this could be done better. If you have any suggestions I'm all ears. This is very much a WIP ...
Feb 13, 2023, 11:25 AM
the
validation
data is exposed in a number of areas in the
props
. I choose the
props.schemaType
as opposed to
props.validation
but I'm not sure why multiple validation types are in the props? What is the purpose of
validationError
? Does this provide custom validation error messages defined in the fields schema?
Feb 16, 2023, 4:02 AM

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?