Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

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

default discord avatar
remy_90last year
4

I have the following DOM element select:


<select title="select" value={selectedOption} onChange={(e) => handleChange(e, path)}>
    {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?



<Select name='select' label="my select" options={options} hooks={{
    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)

  • 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!!

  • default discord avatar
    remy_90last year

    Hi @jarrod_not

    jared , 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:
    ``html <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

    : ```typescript // 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 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)}
    />
    Screenshot_2023-05-10_at_16.22.02.png
  • default discord avatar
    aaronksaunderslast year

    i am heading down this journey now, do you have some source code you wouldnt mind sharing

  • default discord avatar
    remy_90last year

    Hey Aaron, I'm hoping to make this publicly available at some point soon, perhaps as a plugin? In the interim, it's currently baked into closed source code, will send a DM for the time being

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.