Setting object schema within a custom input component in Sanity

25 replies
Last updated: Feb 6, 2021
Does anyone have any examples of how to set an object schema within a custom input component? It seems to set the object, as a string, and not get the preview, like
[object Object]
(cc
user Y
)
Feb 5, 2021, 4:07 PM
I believe that
user G
has experience with this in one of her projects.
Feb 5, 2021, 5:19 PM
Thanks
user M
Feb 5, 2021, 5:26 PM
user T
can you share the relevant parts of the code you have? I can probably help, but I’m not positive what you mean.
Feb 5, 2021, 6:09 PM
Hi,
user G
, I have created a custom input component, with its own custom type, like so:
export default {
  name: "product",
  title: "Product",
  type: "object",
  fields: [
    {
      name: "title",
      title: "Title",
      type: "string",
    },
    {
      name: "handle",
      title: "Handle",
      type: "string",
    },
    {
      name: "image",
      title: "image",
      type: "image",
    },
  ],
  preview: {
    select: {
      title: "title",
      media: "image",
    },
  },
}
Then inside my input component, I am trying to render the preview, on the
onChange
event, like so:
const ProductInput = ({
  ...
    
  const handleChange = (hit: ProductItem) => {
      onChange(PatchEvent.from(set(
        { handle: hit.handle, title: hit.title, image: hit.image }
      )))
    setInputValue(null)
    lastQuery = null
  }

  ...
  render ()

  ...
}
Feb 5, 2021, 6:18 PM
However, it displays it as an object and not the preview:
Feb 5, 2021, 6:19 PM
user G
does that make sense 🙂
Feb 5, 2021, 6:53 PM
Ah interesting, I haven’t used the
preview
option on objects, only documents. How are you using the preview? I don’t understand the connection between the schema and
ProductInput
. Are you using the
Preview
part from
'part:@sanity/base/preview'
?
Feb 5, 2021, 6:56 PM
I just changed it to a
document
and still has the same issue. I am just using the preview like I would on any normal document, just set the select fields. I think the issue is in the input component, it doesn't render it, only renders a string. ie
[object Object]
I am also using
SearchableSelect
as the input component:
  return (
    <FormField
      markers={markers}
      label={type.title}
      level={level}
      description={type.description}
    >
      <SearchableSelect
        placeholder="Type to search…"
        title={inputValue}
        customValidity={errors.length > 0 ? errors[0].item.message : ""}
        onOpen={handleOpen}
        onFocus={handleFocus}
        onBlur={handleBlur}
        onSearch={handleSearch}
        onChange={handleChange}
        onClear={handleClear}
        value={value}
        inputValue={inputValue === null ? value : inputValue}
        renderItem={renderHit}
        isLoading={isFetching}
        items={hits}
        ref={inputRef}
        readOnly={readOnly}
      />
    </FormField>
  )

Feb 5, 2021, 7:00 PM
Maybe I need to create my own custom
SearchableSelect
Feb 5, 2021, 7:02 PM
What does your
renderHit
function look like?
Feb 5, 2021, 10:53 PM
  const renderHit = (item: ProductItem) => {
    return (
      <Container>
        <Image src={item.image} />
        <Name>{item.title}</Name>
      </Container>
    )
  }

Feb 5, 2021, 10:54 PM
The rendering of search dropdown is fine, it is once the object has been selected
Feb 5, 2021, 10:54 PM
Ah ok. I think maybe that's caused by the
inputValue
being wrong - where is that variable coming from? Could you try changing the
inputValue
prop to:

inputValue={value ? value.title : undefined}
Feb 5, 2021, 11:03 PM
That displays the title correctly, however I am trying to set an object on the selected item
Feb 5, 2021, 11:14 PM
like so:
export default {
  name: "product",
  title: "Product",
  type: "object",
  fields: [
    {
      name: "title",
      title: "Title",
      type: "string",
    },
    {
      name: "handle",
      title: "Handle",
      type: "string",
    },
    {
      name: "image",
      title: "image",
      type: "image",
    },
  ],
  preview: {
    select: {
      title: "title",
      media: "image",
    },
  },
}

Feb 5, 2021, 11:14 PM
So I get this warning
Feb 5, 2021, 11:15 PM
This is what I am trying to accomplish:
Feb 5, 2021, 11:38 PM
And the object above gets inputted into the dataset
Feb 5, 2021, 11:39 PM
Right - I don't think you will be able to get the image there unless you replace the SearchableSelect component - it just renders a text field at the end of the day
Feb 5, 2021, 11:53 PM
Ok, yeah thats what I thought. Is there another component I could use, or would need to create my own custom component?
Feb 5, 2021, 11:53 PM
I managed to get this working; but if you need the image inline I don't have a clear solution for you at the moment
Feb 5, 2021, 11:55 PM
Yeah I got the dropdown working fine, however once selected we want to submit an object, rather than a text
Feb 5, 2021, 11:56 PM
Thanks for your help, guess I will create my own custom component
Feb 5, 2021, 11:56 PM
The actual change handler works in this example, at least - it stores it as an object and displays the correct title. Here's the full code, in case there are any learnings in here: https://gist.github.com/rexxars/1945c4b1b137cbd6f9b06e147ec4359d
Feb 5, 2021, 11:59 PM
Great, thanks!! Will use that as a base to try and get a custom searchable select
Feb 6, 2021, 12:01 AM

Sanity– build remarkable experiences at scale

The Sanity Composable Content Cloud is the headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?

Categorized in