👀 See Sanity in action: Watch product demo now →

V3 version of Display an array of references as a checklist

By RD Pennell & Rohit Madas

This will allow you to display an array of references as a checklist from which you can multi-select.

Schema.js

{
      name: "ReferenceMultiSelect",
      description: "Select categories",
      title: "Category Type",
      type: "array",
      of: [
        {
          type: "reference",
          to: { type: "categories" },
        },
      ],
      components: {
        input: ReferenceSelect,
      },
 },

ReferenceSelect.jsx

import React, { useEffect, useState } from "react";
import { Card, Flex, Checkbox, Box, Text } from "@sanity/ui";
import client from "./client";
import { useId } from "@reach/auto-id";
import { FormField, PatchEvent, set } from "sanity";

const ReferenceSelect = React.forwardRef((props, ref) => {
  const [categories, setCategories] = useState([]);

  useEffect(() => {
    const fetchCountries = async () => {
      await client
        .fetch(
          `*[_type == 'categories']{
            ...,
             _id,
             category
        }`
        )
        .then(setCategories);
    };
    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?.schemaType.description} // Creates description from schema
      title={type?.schemaType.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}
    >
      {categories.map((cat, index) => (
        <Card key={index} padding={2}>
          <Flex align="center">
            <Checkbox
              id={cat._id}
              style={{ display: "block" }}
              onClick={handleClick}
              onChange={() => console.log("changed")}
              value={cat._id}
              checked={
                value ? value.some((item) => item._ref === cat._id) : false
              }
            />
            <Box flex={1} paddingLeft={3}>
              <Text>
                <label htmlFor={cat._id}>{cat.category}</label>
              </Text>
            </Box>
          </Flex>
        </Card>
      ))}
    </FormField>
  );
});

export default ReferenceSelect;

Contributors

Other schemas by authors