Issues with array field and reference type in navMenu schema

5 replies
Last updated: Jun 11, 2023
The closest I've gotten is by passing an empty span, but that looks horrible. The media's html element in the preview list container has a fixed height and width. I would expect that if I specifically pass null or false to the media property, that it would hide it altogether.
AI Update

Based on the documentation, if you want to hide the media element in preview configurations, the standard approach is to simply omit the media property from your preview configuration entirely.

When you don't need a media preview, just don't include it in your select or prepare functions:

preview: {
  select: {
    title: 'title',
    subtitle: 'description'
    // No media property defined
  }
}

Or if you're using prepare:

preview: {
  select: {
    title: 'title'
  },
  prepare({title}) {
    return {
      title: title,
      subtitle: 'Some subtitle'
      // No media property returned
    }
  }
}

According to the preview configuration documentation, the preview system accepts title, subtitle, and media properties - but they're all optional. You only need to include the ones you want to display.

If you have a field that sometimes has an image, you can conditionally handle it in the prepare function. A common pattern is to use an icon as a fallback when media isn't available:

import { DocumentIcon } from '@sanity/icons'

preview: {
  select: {
    title: 'title',
    image: 'image'
  },
  prepare({title, image}) {
    return {
      title: title,
      media: image ?? DocumentIcon  // Use icon when no image exists
    }
  }
}

This approach is shown in the Page Building course as a best practice for handling optional media.

The key takeaway: you don't need to pass null or false to hide media - just don't include the media property at all in your preview configuration. This is the documented, standard way to control what appears in your previews.

UPDATE: solved, but not sure if this is the best way
Okay, I've got another related issue: The screenshot above is of my navMenu schema. I've set up a field of type
array
and it can take custom objects such as
menuItem
, but it can also take a
reference
type to itself,
navMenu
, so that I can have sub menus. My issue is I'm not getting the expected data in the list previews. What's odd to me (because I'm still learning Sanity) is that the correct icon will show up for the
reference
type, but for everything else I'm getting
undefined
. I'm probably doing something wrong.
If I do it like this:


 defineField({
   name: "items",
   title: "Menu Items", // e.g. 'Categories', 'Sale'
   type: "array",
   of: [
     { type: "menuItemWithIcon" }, // e.g. 'New Arrivals', 'Tops', etc.
     { type: "menuItemWithImage" },
     { type: "reference", to: [{ type: "navMenu" }] },
   ],
   validation: (Rule) => [Rule.min(1), Rule.unique()],
}),
the result is like this:
As you can see, the validation is working, as are the titles, but I want to use a different icon to better represent a submenu item.
So I resorted to something I did in another schema, but feels hacky:

defineField({
    // doing this so I can alter the appearance of the menuItem in the dropdown, but I lose the ability to reference the data in the preview
    name: 'submenu',
    title: 'Sub Menu',
    type: 'object',
    icon: BsListNested,
    preview: {
       select: {
          // NOT SURE WHAT TO SELECT HERE??
          title: 'navMenu',
       },
       prepare({ title }) {
           console.log('title', title);
           return {
             title: title,
             media: BsListNested,
           };
        },
     },
     fields: [
        defineField({
          name: 'submenuReference',
          type: 'reference',
          to: [{ type: 'navMenu' }],
        }),
      ],
}),
and the result I get with this spaghetti code is:
I don't know what to select in the preview object. Everything I try comes back as
undefined
.
Golly bum! I know I tried this
title: 'submenuReference.title'
and was still getting
undefined
, but now it's working as expected. However, do I really have to define an inline object like that to achieve the desired result or is there a more concise way?

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?