Rune Rapley-Møller
Passionate JavaScript Progammer
Rune is located at Berlin/Germany
A custom input component that conditionally shows fields in from the 'fields' array
This schema is for an older version of Sanity Studio (v2), which is deprecated.
Learn how to migrate to the new Studio v3 →import ConditionalFields from "../components/ConditionalFields"
export default {
name: 'conditionalFields',
title: 'Condition Fields Title',
type: 'object',
inputComponent: ConditionalFields,
fields: [
// First field is mandatory and needs to be a Boolean with the name: `conditionalsToggled`
{
name: 'conditionalsToggled',
title: 'Call To Action',
type: 'boolean'
},
// Example of a Call To Action Button with a title and url field
{
name: 'callToActionTitle',
title: 'Button Title',
type :'string'
},
{
name: 'callToActionUrl',
title: 'Button Url',
type: 'url'
}
]
}
import React from "react";
import { FormBuilderInput } from "@sanity/form-builder/lib/FormBuilderInput";
import Fieldset from "part:@sanity/components/fieldsets/default";
import { setIfMissing } from "@sanity/form-builder/PatchEvent";
const ConditionalFields = React.forwardRef((props, ref) => {
// destructure props for easier use
const {
compareValue,
focusPath,
markers,
onBlur,
onChange,
onFocus,
presence,
type,
value,
level,
} = props;
const firstFieldInput = React.createRef();
const handleFieldChange = React.useCallback(
(field, fieldPatchEvent) => {
onChange(
fieldPatchEvent
.prefixAll(field.name)
.prepend(setIfMissing({ _type: type.name }))
);
},
[onChange]
);
// Get an array of field names for use in a few instances in the code
const fieldNames = type.fields.map((f) => f.name);
// If Presence exist, get the presence as an array for the children of this field
const childPresence =
presence.length === 0
? presence
: presence.filter((item) => fieldNames.includes(item.path[0]));
// If Markers exist, get the markers as an array for the children of this field
const childMarkers =
markers.length === 0
? markers
: markers.filter((item) => fieldNames.includes(item.path[0]));
return (
<Fieldset
level={level}
legend={type.title}
description={type.description}
isCollapsible={!!type.options && !!type.options.collapsible}
isCollapsed={!!type.options && !!type.options.collapsed}
markers={childMarkers} // markers built above
presence={childPresence}
>
{type.fields.map((field, i) => {
const fieldMarkers = markers.filter((marker) =>
marker.path.includes(field.name)
);
return (
// Delegate to the generic FormBuilderInput. It will resolve and insert the actual input component
// for the given field type
<div key={i}>
{field.type.jsonType === "boolean" && (
<FormBuilderInput
level={level + 1}
ref={i === 0 ? firstFieldInput : null}
key={field.name}
type={field.type}
value={value && value[field.name]}
onChange={(patchEvent) => handleFieldChange(field, patchEvent)}
path={[field.name]}
markers={fieldMarkers}
focusPath={focusPath}
readOnly={field.readOnly}
presence={presence}
onFocus={onFocus}
onBlur={onBlur}
compareValue={compareValue}
/>
)}
{(value['conditionalsToggled'] && field.type.jsonType !== 'boolean') && (
<FormBuilderInput
level={level + 1}
ref={i === 0 ? firstFieldInput : null}
key={field.name}
type={field.type}
value={value && value[field.name]}
onChange={(patchEvent) => handleFieldChange(field, patchEvent)}
path={[field.name]}
markers={fieldMarkers}
focusPath={focusPath}
readOnly={field.readOnly}
presence={presence}
onFocus={onFocus}
onBlur={onBlur}
compareValue={compareValue}
/>
)}
</div>
);
})}
</Fieldset>
);
});
export default ConditionalFields;
Sanity Studio now has support for conditional fields natively. Check out the official documentation.
A simple custom input component that gives your editor the possibility of turning fields on and off. Your Frontend can then query the boolean to conditionally render the ui components that uses the schema fields.
How to use
Passionate JavaScript Progammer