Using slug source from array child in Sanity

10 replies
Last updated: Jul 5, 2021
Hey all, is it possible to use the slug source from a child (type of array)?
AI Update

Yes, absolutely! You can use the slug source option with fields from a child object in an array. The key is using the parent parameter in the source function.

When you define a slug field inside an object type (especially one used in an array), you can access the parent object's fields using a function for the source option:

{
  name: "contentBlock",
  type: "object",
  fields: [
    {
      name: "title",
      type: "string",
    },
    {
      name: "slug",
      type: "slug",
      options: {
        source: (doc, { parent }) => parent?.title
      }
    }
  ]
}

The naming can be a bit confusing here - parent actually refers to the immediate parent object (the current contentBlock in this case), not the top-level document. So parent.title gives you the title field from the same object where your slug lives.

This is particularly useful when you have an array of objects and want each item to generate its own slug based on its own fields:

{
  name: "page",
  type: "document",
  fields: [
    {
      name: "content",
      type: "array",
      of: [{ type: "contentBlock" }]
    }
  ]
}

Each contentBlock in the array can now generate its slug from its own title field rather than trying to reference something at the document level.

This feature was added to Sanity back in 2019 and works great for creating slugs in nested structures. The parent parameter gives you exactly what you need to reference fields within the same object context.

Show original thread
10 replies
How do you mean, sorry I'm new to this? I'm just trying to get the slug to generate from the child title not parent.
Oh, sorry. I think I misread. So you want
slug
for the object to generate from “Your First Visit?”
Yes, I;ve set the slug source to the child title in the js file but its pulling the source title from the parent.
Okay, I follow you. Thank you.
To accomplish this I think you’ll need to
return a function for source :

options: {
source: (doc) => {
return doc.child[0].title
}
}
Edit: The above isn’t quite right. It’ll base the slug on the first item in the array. You’ll want to access the second parameter of the source function. The underscore is convention for a parameter we don’t need.


options: {
  source: (_, { parent }) => {
    return parent.title
  }
}
Here’s a complete schema, in case the above isn’t clear:

export default {
  name: 'jeanmarc',
  title: 'Jean-Marc',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'title',
      type: 'string',
    },
    {
      name: 'child',
      title: 'Child',
      type: 'array',
      of: [
        {
          name: 'obj',
          title: 'Obj',
          type: 'object',
          fields: [
            {
              name: 'title',
              title: 'title',
              type: 'string',
            },
            {
              name: 'slug',
              title: 'Slug',
              type: 'slug',
              options: {
                source: (doc) => {
                  return doc.child[0].title
                }
              }
            }
          ]
        }
      ]
    }
  ]
}
Thanks for that! Apprecaite it 🙂 Will give it a shot.
Thanks for the reply!Would this work if im referencing the child document ? like the below

parent.js

name: "childCard",
title: "Child Services",
type: "array",
of: [{ type: "servicesChild" }],
Yes, this should work even when using references. I’ve edited my previous post as the first code wasn’t quite right.

export default {
  name: 'jeanmarc',
  title: 'Jean-Marc',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'title',
      type: 'string',
    },
    {
      name: 'childCard',
      title: 'Child Services',
      type: 'array',
      of: [{ type: 'servicesChild' }]
    }
  ]
}

export default {
  name: 'servicesChild',
  title: 'Child Services',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'title',
      type: 'string',
    },
    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: (_, {parent}) => {
          return parent.title
        }
      }
    }
  ]
}
Thank you! I would love to learn more on this, is there any docuemntation on the methods we can pass?
I’m not aware of any docs other than what’s at https://www.sanity.io/docs/slug-type#source-9a89f442eaea , but if you pass in both arguments and then log the results, you can get some insight into what they enable.

options: {
  source: (doc, options) => {
    console.log('doc', doc);
    console.log('options', options);
  }
}

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?