How to select multiple items from a reference field dropdown in Sanity?

13 replies
Last updated: Sep 3, 2021
{ name:"category",
title:"Category",
type:"reference",
to: { type: "category" },

inputComponent: conditionalFields,
options:{

condition: (document, parent) => parent.articleType != "shortStories"
},
},
I want to select multiple items from the dropdown is it possible?
AI Update

Yes! To select multiple items from a dropdown, you need to change your field from a single reference type to an array of references. Here's how to modify your schema:

{
  name: "category",
  title: "Category",
  type: "array",  // Changed from "reference" to "array"
  of: [
    {
      type: "reference",
      to: { type: "category" }
    }
  ],
  inputComponent: conditionalFields,
  options: {
    condition: (document, parent) => parent.articleType != "shortStories"
  }
}

The key changes are:

  1. Change type to "array" - This makes the field hold multiple items
  2. Add an of property - This defines what types can be in the array (in your case, references to category documents)

This will give you a multi-select interface where you can add multiple category references. Users can click to add categories, reorder them via drag-and-drop, and remove them individually.

The array field type in Sanity is specifically designed for storing orderable collections of items, and it's the standard way to handle multiple selections. Each selected item automatically gets a unique _key property that Sanity uses to track items.

If you need to query these multiple references later in GROQ, you can use array operations like:

*[_type == "yourDocType"] {
  title,
  "categories": category[]->title
}

The []-> syntax dereferences all items in the array, giving you the full category documents.

Show original thread
13 replies
i tried this but didn't work{
title: 'Category',
name: 'categories,
type: 'array',
of: [
{
type: 'reference',
to: [
{type: 'category'},

]
}
]
},
This above works but when i do :inputComponent: conditionalFields,
            options:{

              condition: (document, parent) => parent.articleType != "shortStories"
             },
it does not work it gives blank can anyone help me.
Yes, I am using the conditionalField package to hide that field when articleType=="shortStories". When i use conditionalField i am getting this above error but when i remove the conditionalField it works perfect.
Yes, I am using the conditionalField package to hide that field when articleType=="shortStories". When i use conditionalField i am getting this above error but when i remove the conditionalField it works perfect.
I am using conditionalField file.import PropTypes from "prop-types";
import React from "react";
import * as PathUtils from '@sanity/util/paths'
import { FormBuilderInput, withDocument, withValuePath } from "part:@sanity/form-builder";


/**
* ConditionalField input component will wrap any regular input field configured
* with
options.condition
in the schema. *
*
option.condition
should be a function that accepts two parameters,
document
* and
parent
, and returns
true
if the wrapped field should be shown. *
* Inspired by the following code examples:
* -
https://sanity-io-land.slack.com/archives/C9Z7RC3V1/p1583362492389300?thread_ts=1583335061.341000&cid=C9Z7RC3V1 * -
https://github.com/sanity-io/sanity-recipes/blob/master/snippets/conditionalFieldsCustomInputComponent.js */

class ConditionalField extends React.Component {

// Declare shape of React properties
static propTypes = {
type: PropTypes.shape({
title: PropTypes.string,
options: PropTypes.shape({
condition: PropTypes.func.isRequired
}).isRequired
}).isRequired,
level: PropTypes.number,
focusPath: PropTypes.array,
onFocus: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onBlur: PropTypes.func.isRequired
};

// Reference to input element
_inputElement = React.createRef();

// Called by the Sanity form-builder when this input should receive focus
focus() {
if (this._inputElement.current) {
this._inputElement.current.focus();
}
}

// Renders the form input if condition function returns true
render() {
const { document, getValuePath, value, level, focusPath, onFocus, onBlur, onChange } = this.props;

// Extract type without 'inputComponent' (self reference) to avoid infinite loop
const { inputComponent, ...type } = this.props.type;

// Find the active field's parent object in the document
const parentPath = getValuePath().slice(0, -1); // <- Remove current field from path
const parent = PathUtils.get(document, parentPath);

// Condition to evaluate if component should be shown, defaults to true
const defaultCondition = () => false;
const condition = (type.options && type.options.condition) || defaultCondition;

if (!condition(document, parent)) {

// Hide component
return null;

/**
* ----------------------------------------------------------------
* QUESTION
* How can we also delete the field value from the stored document?
* Running patch unset seems inefficient if it unsets the field
* every time the Studio UI is rendered, even though the stored
* document has not changed, but might be an acceptable solution.
* ----------------------------------------------------------------
*/

} else {

// Render component
return (
<div>
<FormBuilderInput
level={level}
ref={this._inputElement}
type={type}
value={value}
onChange={onChange}
path={[]}
// focusPath={focusPath}
onFocus={onFocus}
onBlur={onBlur}
/>
</div>
);

}

}

}

export default withValuePath(withDocument(ConditionalField));
When i use this in category it does not refer to category i guess so and adds empty item.
One thing that may help: we recently released conditional fields within out of the box Studios. If you upgrade your studio, you can take advantage of this and simplify your schema.
How to upgrade the studio how to use it
You can upgrade the studio using
sanity upgrade
and the link in the reply above will take you through the usage!
{ name: "articleType",
type: "string",
title: "Select Article Type",
initialValue:"Text",
options: {

list: [
{ title: "Text", value: "Text" },
{ title: "Audio", value: "audio" },
{ title: "Video", value: "video" },
{title:"Habit Cards", value:"cards"},
{title:"Short Stories", value:"shortStories"},
],
},
},
{
title: 'Categories',
name: 'categories',
type: 'array',
of: [
{
type: 'reference',
to: [
{type: 'category'},
]
}
],
hidden: ({ parent, value }) => parent.articleType==="shortStories",
},
I am doing this it does not display the category field in any condition can you please help.I want to hide when the articleType=="shortStories" how can i achieve that
It worked for me on restarting server! How can i restricted that selecting reference doesn't get duplicated? like same category name cannot be selected multiple times.
Also want to add on how can i do conditional validation like when this field is not hidden i want it to be required.
Also want to add on how can i do conditional validation like when this field is not hidden i want it to be required.

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?