custom field component: save to database (solved) and reflect back (solved)?

default discord avatar
unonweb10 months ago
1 2

Hi community,
I've guess this is an easy one for you:
How can I make this custom color picker component save to the database when the overall form is submitted?

const colorPickerField = (props) => {
  const { path, label, required } = props
  const {
    value = '25', // the current value of the field from the form
    setValue, // method to set the field's value in form state
    initialValue = 5, // the initial value that the field mounted with 
  } = useFieldType({ path })

  return (
    <div>
      <Label
        htmlFor={path}
        label={label}
        required={required}
      />
      <input
        type='color'
        onChange={evt => setValue(evt.target.value)}
        value={value.path}
      />
    </div>
  )
}

export default colorPickerField

Sorry for my lack of React knowledge.

  • Selected Answer
    default discord avatar
    unonweb8 months ago

    I think I've got it finally (consider that this is my first time to deal with React code):
    This colorPickerField initializes with the defaultValue from where the field is used and saves the new color in a preference using it's path within the payload collection as a key ('colors.primary').
    I'm pretty happy now.

    const colorPickerField = (args) => {
      // payload:
      // args.name: "primary"
      // args.path: "colors.primary"
      // args.defaultValue: "#74ea94"
      const { path, label, required } = args
      const { value, setValue } = useField({ path })
      const { getPreference, setPreference } = usePreferences()
      // react:
      const [color, setColor] = useState(args.defaultValue)
    
      useEffect(() => {
        async function getColorFromPayload() {
          const color = await getPreference(args.path);
          if (color) {
            setColor(color)
          }
        }
    
        getColorFromPayload()
    
      }, [getPreference]);
    
      const updateColor = useCallback(newColor => {
        setValue(newColor)
        setColor(newColor)
        setPreference(args.path, newColor)
      }, [color, setPreference])
    
      return (
        <div>
          <Label
            htmlFor={path}
            label={label}
            required={required}
          />
          <input
            type='color'
            onChange={(evt) => updateColor(evt.target.value)}
            value={color}
          />
        </div>
      )
    }
    
    export default colorPickerField
    ``
  • default discord avatar
    unonweb8 months ago

    Alright, I'v got the solution. The issue was not with the colorPicker component but with the way I used it. I tried it with field type = 'ui' and it didn't save to the database. Now I have this:

    {
      type: 'text',
      name: 'primary',
      label: {
        de: 'Primäre Farbe',
        en: 'Primary Color'
      },
      admin: {
        components: {
          Field: colorPickerField,
        },
      },
      defaultValue: `#${Math.floor(Math.random() * 16777215).toString(16)}`
    },

    ... and it works great!

    1 reply
    default discord avatar
    unonweb8 months ago

    Damn! Now it saves to the database but it doesn't reflect the database value on the color component...
    I'm sure it has to do with value={value.path} somehow...

    cconst colorPickerFieldNew = ({ path, label, required }) => {
      const { value, setValue } = useField({ path })
    
      return (
        <div>
          <Label
            htmlFor={path}
            label={label}
            required={required}
          />
          <input
            type='color'
            onChange={evt => setValue(evt.target.value)}
            value={value.path}
          />
        </div>
      )
    }
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.