#hooks on { Select } from 'payload/components/forms'

8 messages · Page 1 of 1 (latest)

pulsar yarrow
#

I have the following DOM element select:

    {options.map((option, index) => <option value={option}>{option}</option>)}
  </select>

The above works as expected

I'm trying to use payload's Select, as referenced in the subject title. I imagine hooks is the way to manage state, as onChange isn't provided - but they aren't ever triggered?

    afterChange: [() => console.log('afterChange')],
    beforeChange: [() => console.log('beforeChange')],
    afterRead: [() => console.log('afterRead')],
    beforeValidate: [() => console.log('beforeValidate')],
  }} />```

Am I missing something? I would like to set a default value from `useFormFields` and update the selected value onChange (as achieved in the first example)
restive pivot
#

AH!

#

I linked the wrong import path in our last discussion. 1 min

#

Ok so you will want to import the Select component like so import SelectInput from 'payload/dist/admin/components/forms/field-types/Select/Input'; (see the component here: https://github.com/payloadcms/payload/blob/master/src/admin/components/forms/field-types/Select/Input.tsx)

This will give you the styled component - so it looks and feels like other payload select components.

What you need to do is implement similar functionality seen in this file in your custom Field component: https://github.com/payloadcms/payload/blob/master/src/admin/components/forms/field-types/Select/index.tsx

You can see how that file imports the <SelectInput /> which is the one you will import, all of the state management (getting and setting options for your custom select) will live in a file that then passes props (onChange, value, options, etc) down to the SelectInput component.

I hope this makes sense and steers you in the right direction!!

pulsar yarrow
#

Hi @restive pivot , I'm back! Following your recommendation above I have the following:

<SelectInput
  path={p}
  name='l'
  label='logic'
  options={options.map(option => option...)}
  onChange={e => handlePrerequisiteChange(e, path)}
/>

The above doesn't persist between refreshes.

The following sometimes works when another field is updated:

<select
  title='prerequisite'
  value={selectedOption}
  onChange={e => handlePrerequisiteChange(e, path)}
>
  {options.map((option, index) => (
    <option key={`r-${index}`} value={`${option.question}_${option.answer}`}>
      {`${option.question}_${option.answer}`}
    </option>
  ))}
</select>
  • I'm still using useFormFields, I can't see how to make use of useFields (without violating react hook laws). How could I update each dropdown with useFields? My implementation is below

  • Changing an option in my select won't trigger the clean/dirty flag for saving/publishing changes but sometimes persists when other fields change

Hopefully the content below will help paint a picture of what I'm working with and why I chose useFormFields:

// fields param is from:
// const { fields, dispatch } = useFormFields(([fields, dispatch]) => ({ fields, dispatch }))
const generateOptions: (fields: any) => string[] = fields => {
  const numberOfPages = pageState.pages.value

  const questionCombination = [...Array(numberOfPages).keys()].flatMap(pageNo =>
    getAnswerOptionsFromAnswerTypes( // checks if boolean/multiple choice, etc
// assuming there is currently only one question and answer
      fields[`pages.${pageNo}.content.questions.0.answerType.0.blockType`],
    ).map<ConditionalLogicOptions>(option => ({
      question: fields[`pages.${pageNo}.content.questions.0.text`].value,
      answer: fields[`pages.${pageNo}.content.questions.0.answerType.0.${option}`]?.value || '',
    })),
  )

  return questionCombination
}
#

Here's a screenshot displaying the dropdown comprised of state from multiple fields.

using useField for the selectedValue triggers the clean/dirty flag for saving a draft/publishing and reloading sends it back to its previous value, so it's still not persisting

pulsar yarrow
#

Progress!
I've used useField instead of useState to set the selectedOption. That sorts out my clean/dirty and the reload.

The only remaining issue is converting my un-styled select to your SelectInput. My select HTML is still as above. I'm getting page ids coming through for the dropdown when I use the following:

<SelectInput
  path={path}
  name='logic'
  label='logic'
  options={options.map((option) => ({</option>)
    label: option,
    value: option
  }))}
  onChange={e => handlePrerequisiteChange(e, path)}
/>
half radish