sanity icon indicating copy to clipboard operation
sanity copied to clipboard

Allow dynamic `options.list` for String type schema

Open saiichihashimoto opened this issue 2 years ago • 10 comments

Is your feature request related to a problem? Please describe. I want to create dynamic fields based on other fields. I need some behaviour like filter in references. There is built-in list for String schema which is fine, but I need the list to be dynamic, based on other field. The biggest use case for me is when I'm putting in an address and have country and region fields. The available regions is dependent on which country I pick.

Describe the solution you'd like Implement

type StaticList = Array<string> | Array<{title: string; value: string}> 
type StringOptionsList = StaticList | (docOptions) => StaticList

Describe alternatives you've considered Nothing else really solves what I wanted

This is essentially a copy of #2821, which was autoclosed.

saiichihashimoto avatar Jan 14 '23 07:01 saiichihashimoto

I was working on something like this (if I understand correctly). Keep in mind that's code for v3 but I haven't checked if it was working on the latest 3.x because I moved to another project at work.

Custom input component:

function ListOverrideField(props: StringInputProps) {
  const document = useFormValue([])
  //@ts-ignore
  props.schemaType.options.list = props.schemaType.options.listGenerator({
    document,
    path: props.path,
  })
  return props.renderDefault(props)
}

Usage:

defineField({
  name: 'group',
  title: 'Group',
  description: 'Decide if this variant is standalone or belongs to a group',
  type: 'string',
  components: {
    input: ListOverrideField,
  },
  options: {
    //@ts-ignore
    listGenerator: ({document}) => {
      const groups = (document.productVariantsGroups || []).map((group) => {
        return {title: group.name, value: group._key}
      })
      return [{title: 'None', value: undefined}].concat(groups)
    },
    layout: 'radio',
  },
}),

I had to add a few @ts-ignore because the default types are not ready for this kind of wizardry, but basically in this configuration the possibles string values for the group field are generated based on the values inside the productVariantsGroups field of the same document.

tbassetto avatar Jan 18 '23 13:01 tbassetto

Was there any progress on this? I've been searching documentation

ikennai avatar Nov 16 '23 02:11 ikennai

Besides @tbassetto's custom component, no, I don't think so.

saiichihashimoto avatar Nov 16 '23 02:11 saiichihashimoto

@tbassetto Is there a way to execute a grok query in the list generator function?

ShakeebAftab avatar Mar 25 '24 12:03 ShakeebAftab

@tbassetto Is there a way to execute a grok query in the list generator function?

We could find a way to pass down the client to listGenerator but it cannot be an async function so I am afraid we can't execute a GROQ query no.

tbassetto avatar Mar 25 '24 15:03 tbassetto

Would be great if the API was simply:

{
  name: '...',
  type: 'string',
  options: {
    list: async () => {
      const res = await ...
      return res // { title: '...', value: '...' }[]
    }
  }
}

sameerxanand avatar Apr 16 '24 05:04 sameerxanand

im with @sameerxanand this would be awesome

sebbean avatar May 19 '24 23:05 sebbean

I know this is still not as direct as you might like, but I've used this pattern to build an options list based on the value of another field. Using a custom component.input to create the list allows for the use of useFormValue, useClient hooks or any other hooks, if needed.

But having a way to do this more directly would be cool too. Just thought I'd add this here in case someone stumbles on this and needs an immediate solution.

krsteele avatar Aug 04 '24 01:08 krsteele

Yeah I would love similar functionality like this but to generate a an options.list attribute filled with slugs from other documents I have in my Sanity database.

This could solve the problem of doing internal linking a bit more developer-friendly, as you would be able to get slug fields without references, and therefore no need to expand your GROQ query everytime there is a link.

Keen to see any follow up or if anyone has an idea for my use case!

LushawnDev avatar Aug 08 '24 11:08 LushawnDev