Racheal Pennell
Community Engineer at Sanity.io
Racheal is located at Richmond, CA
{
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 { studioClient } from '../../lib/utils/studioClient';
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='checkbox'
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 htmlFor='checkbox'>{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
Add a count of documents to your Structure Builder panes
Go to Display a document count in the title of a pane in Structure BuilderSanity preview component cannot access the parent/document if its inside an array or object. Using Custom Preview component, we can solve the issue.
Go to Sanity Custom Preview Component to get Parent DocumentIf you'd like to be able to reference your project users within your content, you'll need to create a document for them.
Go to Create A Document for All Current Project UsersUse a publishedOnce field to control other fields.
Go to Make a Field Read-Only After Publishing Once