RD Pennell
Community Engineer at Sanity.io
RD is located at Richmond, CA
This schema is for an older version of Sanity Studio (v2), which is deprecated.
Learn how to migrate to the new Studio v3 → {
name: 'ReferenceMultiSelect',
description: 'This will create a multiselect checkbox list of references',
title: 'Country',
type: 'array',
of: [
{
type: 'reference',
to: { type: 'country' },
},
],
inputComponent: ReferenceSelect,
},
import React, { useEffect, useState } from 'react';
import { Card, Flex, Checkbox, Box, Text } from '@sanity/ui';
import { FormField } from '@sanity/base/components';
import PatchEvent, { set, unset } from '@sanity/form-builder/PatchEvent';
import { useId } from '@reach/auto-id';
import client from 'part:@sanity/base/client';
const studioClient = client.withConfig({ apiVersion: '2021-10-21' });
const ReferenceSelect = React.forwardRef((props, ref) => {
const [countries, setCountries] = useState([]);
useEffect(() => {
const fetchCountries = async () => {
await studioClient
.fetch(
`*[_type == 'country']{
_id,
title
}`
)
.then(setCountries);
};
fetchCountries();
}, []);
const {
type, // Schema information
value, // Current field value
readOnly, // Boolean if field is not editable
markers, // Markers including validation rules
presence, // Presence information for collaborative avatars
compareValue, // Value to check for "edited" functionality
onFocus, // Method to handle focus state
onBlur, // Method to handle blur state
onChange, // Method to handle patch events,
} = props;
const handleClick = React.useCallback(
(e) => {
const inputValue = {
_key: e.target.value.slice(0, 10),
_type: 'reference',
_ref: e.target.value,
};
if (value) {
if (value.some((country) => country._ref === inputValue._ref)) {
onChange(
PatchEvent.from(
set(value.filter((item) => item._ref != inputValue._ref))
)
);
} else {
onChange(PatchEvent.from(set([...value, inputValue])));
}
} else {
onChange(PatchEvent.from(set([inputValue])));
}
},
[value]
);
const inputId = useId();
return (
<FormField
description={type.description} // Creates description from schema
title={type.title} // Creates label from schema title
__unstable_markers={markers} // Handles all markers including validation
__unstable_presence={presence} // Handles presence avatars
compareValue={compareValue} // Handles "edited" status
inputId={inputId} // Allows the label to connect to the input field
readOnly={readOnly}
>
{countries.map(country => (
<Card padding={2}>
<Flex align='center'>
<Checkbox
id={country._id}
style={{ display: 'block' }}
onClick={handleClick}
value={country._id}
checked={
value ? value.some((item) => item._ref === country._id) : false
}
/>
<Box flex={1} paddingLeft={3}>
<Text>
<label for={country._id}>{country.title}</label>
</Text>
</Box>
</Flex>
</Card>
))}
</FormField>
);
});
export default ReferenceSelect;
This will allow you to display an array of references as a checklist from which you can multi-select.
Note: It's a bit of a cursed component. If you have a large number of documents, the options will be incredibly long and may impact performance and/or look ugly. Exercise caution when trying to implement!
Community Engineer at Sanity.io
Use the renderDefault method to show or hide fields.
Go to Conditionally show a field based off of a value inside of a referenceThis will allow you to display an array of references as a checklist from which you can multi-select.
Go to V3 version of Display an array of references as a checklistPopulate your list options in a string schema using an external API
Go to Asynchronous List Options ComponentUse the renderDefault function to easily control your available array options.
Go to Filter Array Options Based on the Current User Role