Using a custom input component to solve a schema problem in Sanity
3 replies
Last updated: Sep 20, 2022
T
Hi I am working on a schema and got stuck on this. Is there any simple way to use one field value as an index in the next field in sanity?
{ name: "tagType", title: "Tag Type", type: "string", options: { list: [ { title: "Activity", value: "activity" }, { title: "Equipment", value: "equipment" }, { title: "Category", value: "category" }, { title: "Duration", value: "duration" }, ], }, }, { name: "tagText", title: "Tag Text", type: "string", options: { list: tagTextOptions[document?.tagType], <-------- here }, }, /* this is const is in the same document const tagTextOptions = { category: [ { title: "Strength", value: "strength" }, { title: "Cardio", value: "Cardio" }, ], equipment: [{ title: "Dumbbell", value: "dumbbell" }], activity: [ { title: "Walking", value: "walking" }, { title: "Running", value: "running" }, ], } */
Sep 15, 2022, 12:08 PM
R
You'd have to use a custom input component here, since your schema won't be aware of the current
document.tagTypewhen the Studio compiles. Something like this should work:
import ConditionalSelect from '../components/ConditionalSelect'; //other document schema { name: 'tagType', title: 'Tag Type', type: 'string', options: { list: [ { title: 'Activity', value: 'activity' }, { title: 'Equipment', value: 'equipment' }, { title: 'Category', value: 'category' }, { title: 'Duration', value: 'duration' }, ], }, }, { name: 'tagText', title: 'Tag Text', type: 'string', options: { list: [], tagTextOptions: { category: [ { title: 'Strength', value: 'strength' }, { title: 'Cardio', value: 'Cardio' }, ], equipment: [{ title: 'Dumbbell', value: 'dumbbell' }], activity: [ { title: 'Walking', value: 'walking' }, { title: 'Running', value: 'running' }, ], }, }, inputComponent: ConditionalSelect, },
./components/ConditionalSelect import React from 'react'; import { Card, Stack, Select } from '@sanity/ui'; import { FormField } from '@sanity/base/components'; import PatchEvent, { set, unset } from '@sanity/form-builder/PatchEvent'; import { withDocument } from 'part:@sanity/form-builder'; import { useId } from '@reach/auto-id'; const ConditionalSelect = React.forwardRef((props, ref) => { const { type, // Schema information value, // Current field value readOnly, // Boolean if field is not editable markers, // Markers including validation rules presence, // Presence information for collaborative avatars compareValue, // Value to check for "edited" functionality onFocus, // Method to handle focus state onBlur, // Method to handle blur state onChange, // Method to handle patch events, document, //Document values } = props; const inputId = useId(); const tagTextOptions = type.options.tagTextOptions; // Creates a change handler for patching data const handleChange = React.useCallback( // useCallback will help with performance event => { const inputValue = event.currentTarget.value; // get current value // if the value exists, set the data, if not, unset the data onChange(PatchEvent.from(inputValue ? set(inputValue) : unset())); }, [onChange] ); return ( <FormField description={type.description} // Creates description from schema title={type.title} // Creates label from schema title __unstable_markers={markers} // Handles all markers including validation __unstable_presence={presence} // Handles presence avatars compareValue={compareValue} // Handles "edited" status inputId={inputId} > <Card padding={0}> <Stack> <Select id={inputId} fontSize={2} padding={[2, 2, 3]} space={[3, 3, 4]} value={value} // Current field value readOnly={readOnly} // If "readOnly" is defined make this field read only onFocus={onFocus} // Handles focus events onBlur={onBlur} // Handles blur events ref={ref} onChange={handleChange} // A function to call when the input value changes > <option value={'---'}>---</option> {tagTextOptions[document.tagType] && tagTextOptions[document.tagType].map(({ value, title }) => ( <option key={value} value={value}> {title} </option> ))} </Select> </Stack> </Card> </FormField> ); }); export default withDocument(ConditionalSelect);
Sep 19, 2022, 10:44 PM
T
Thank you so much for this example. Really appreciated.
Sep 20, 2022, 9:21 AM
R
You're welcome!
Sep 20, 2022, 3:07 PM
Sanity– build remarkable experiences at scale
The Sanity Composable Content Cloud is the headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.