✨ Asynchronous ✨ multiple fields ✨ Sanity UI ✨ Easy! ✨
Show multiple fields in an object field, based on a condition set through the "options" object. Simply return true/false from "condition" function, even asynchronously! You have access to the entire document object, and the context() function
First, drop the conditional-field.js
file somewhere in your Studio, I like putting custom components in a "components" folder, matching my front-end setup.
Then, from your schema import the file:
import ConditionalFields from '../components/conditional-field'
Finally, you can begin wrapping the fields you want to show/hide based on a condition in an object field like this:
{
name: 'objectTitle',
title: 'object Title'
type: 'object',
options: {
condition: (document: obj, context: func) => bool
}
fields : []
}
It's common to offer links to internal "pages" and external URLs. Here's an example that lets you toggle between both options and only show the corresponding fields necessary for each.
{
title: 'Link',
name: 'customLink',
type: 'object',
fields: [
{
title: 'Type',
name: 'type',
type: 'string',
options: {
list: [
{ title: 'Internal Page', value: 'internal' },
{ title: 'External URL', value: 'external' }
],
layout: 'radio',
direction: 'horizontal'
}
},
{
name: 'internal',
type: 'object',
inputComponent: ConditionalFields,
fields: [
{
title: 'Internal Page',
name: 'page',
type: 'reference',
to: [{ type: 'page' }]
}
],
options: {
condition: (_, context) => context().type === 'internal'
}
},
{
name: 'external',
type: 'object',
inputComponent: ConditionalFields,
fields: [
{
title: 'External URL',
name: 'url',
type: 'url'
}
],
options: {
condition: (_, context) => context().type === 'external'
}
}
]
}
Say you have a dynamic "page" document and you want to recreate the famous Wordpress "reading" settings where the user can define their "Homepage" and "Posts page", with conditional fields you can do this pretty easily! Here, we fetch a page reference set in a generalSettings "singleton" and compare it against the current document to determine if we should show some additional fields for the designated "Blog" page document only.
{
name: 'blog',
type: 'object',
inputComponent: ConditionalFields,
fields: [
// your conditional fields
],
options: {
condition: (document, _) => {
return client
.fetch(
`*[_type == "page" && _id == *[_type=="generalSettings"][0].blog->_id] | order(_updatedAt desc)[0]`
)
.then(blog => {
if (!blog?.slug) return false
return document.slug.current === blog.slug.current
})
}
}
}
Adapted from @coxmi's solution here: https://gist.github.com/coxmi/f41aef54d46588fff27651cd0d35212f