Saskia Bobinska
Senior Support Engineer @Sanity
Sometimes you want to validate items in an array, here is how
import { VscBrowser, VscMegaphone } from "react-icons/vsc";
import { isUniqueAcrossAllDocuments } from '../../src/isUniqueAcrossAllDocuments'
import SlugInput from 'sanity-plugin-better-slug'
import { basePath } from "../../src/basePath";
export default {
name: 'landingpage',
title: 'Landingpage',
type: 'document',
icon: VscBrowser,
groups: [
{
name: 'meta',
title: 'Meta',
}
],
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
initialValue: 'Landingpage',
},
{
title: 'Slug',
name: 'slug',
type: 'slug',
inputComponent: SlugInput,
readOnly: false,
options: {
basePath: basePath,
isUnique: isUniqueAcrossAllDocuments,
source: 'title',
maxLength: 200, // will be ignored if slugify is set
slugify: input => input
.toLowerCase()
.replace(/\s+/g, '-')
.slice(0, 200)
}
},
{
name: 'description',
title: 'Meta & SEO Description',
type: 'text',
description: 'Short and on point – max. 280',
maxLength: 280,
rows: 3,
group: 'meta',
},
{
name: 'image',
title: 'OG Image',
type: 'image',
group: 'meta',
validation: Rule => Rule.required(),
options: {
hotspot: true,
},
},
// Lets say you want to make sure, that only a heroSection OR a headerSection is added to the contentArray, but you need to add at least one...
{
name: 'contentArray',
title: 'Content',
type: 'array',
of: [
{ type: 'heroSection' }, //hero image header section
{ type: 'headerSection' }, // text based header section
{ type: 'textSection' },
{ type: 'cardSection' },
{ type: 'accordionSection' },
{ type: 'furtherLinkSection' },
{ type: 'tabSection' },
{ type: 'cta' }
],
},
],
preview: {
select: {
title: 'title',
subtitle: 'subline',
media: 'image'
}
}
}
{
name: 'contentArray',
title: 'Content',
type: 'array',
//The validation would look something like this:
validation: Rule => Rule.custom(content => {
// get the possible headers from the contentArray (if any are there)
const headers = (content || []).filter(
item =>
item._type === 'heroSection' || item._type === 'headerSection'
)
// create an array with the paths of these header items
const headerPaths = headers.map(
(header, index) => [{ _key: header._key }] || [index]
)
// See if headerPaths is longer then 1, if it is, there are too many headers and we then use the paths to mark the headers in the array and display the error message
return headerPaths.length === 1
? true
: {
message: 'There can only be one header section. Please delete one.',
paths: headerPaths
}
}),
of: [
{ type: 'heroSection' },
{ type: 'headerSection' },
{ type: 'textSection' },
{ type: 'cardSection' },
{ type: 'accordionSection' },
{ type: 'furtherLinkSection' },
{ type: 'tabSection' },
{ type: 'cta' }
],
},
Lets assume, you have a landingpage, where editors can add different page sections in an array called contentArray
.
But since you give the option to start the page with a heroSection or a text based headerSection you need to make sure, that editors don't add both or more to the content array.
You can do so by filtering the array items for the two _types
you want to control and creating a headerPaths
array, which you would also use to find the items and mark them as wrong in case the validation rule is broken.
What makes this so easy is, that you use headerPaths.length()
to determine, if there is more than one header section in the contentArray
of the page and use the passed down path
values (_key
and index
) to attach the error message to the items themselves.
Senior Support Engineer @Sanity
Use a migration script to update all references from one document to another
Go to Update references via Content Migration scriptIf you install plugins or other packages with conflicting (peer) dependencies, you can use this useful workaround to unblock yourself.
Go to What to do when Studio crashes due to conflicts in dependency versions?When creating custom document actions, it can be necessary to check, wether all validation rules are full-filled.
Go to Use the validation status of a document in your custom document actionsOnly return a value when a condition is fulfilled
Go to Conditional values in GROQ queries