Configure form fields in another collection

default discord avatar
superwafflepuffs
last month

I have a use case where I'd like to be able to configure form fields in the admin on the fly depeniding on a relationship.



Requirements:


- relationships require no pre-set fields in the collection config


- relationships have a config field that accepts fieldsSchema


- When relationship is selected collection will populate all fields under path

config[relationshipField]

So far i have someting basic working by hijacking the

<RenderFields>

component inside a UI Field, but there's some holes in my implementation but it doesn't really work.



Is there a prescribed way to dynamically add fields to a form if they aren't predefined in the collection config?



Sample provider





Sample connection





The fields show up but don't sync with data from the form



const [fields, dispatchFields] = useAllFormFields();
  const fieldBuilder = (config) => {
    const renderFields = [];
    for (let field of config) {
      switch (field.type)
      {
        case 'text':
          renderFields.push(
            <TextField
              admin={{}}
              key={field.name}
              name={field.name}
              path={`config.${field.name}`}
              label={field.name}
              onChange={e => {}}
              value={fields.config.value[field.name]}
            />
          );
          break;
        case 'textarea':
          renderFields.push(
            <TextareaField
              admin={{}}
              key={field.name}
              name={field.name}
              path={`config.${field.name}`}
              label={field.name}
              onChange={e => {}}
              value={fields.config.value[field.name]}
            />
          );
          break;
      }
    }
    return renderFields;
  }


That's how I have it rendering the fields so far



bump



I was having too many issues with this implementation. I ended up switching to using an array of key/val pairs for my config and I created a ui field to ensure the correct rows are added to the array when selecting a provider



import { useField, useFormFields, useForm } from 'payload/components/forms';
import React, { useState, useEffect } from 'react'

const EnsureConnectionConfigField: React.FC = () => {
  const { value: providerId } = useField({ path: 'provider' });
  const { addFieldRow, getData } = useForm();

  useEffect(() => {
    (async () => {
      if (providerId) {
        const provider = await fetch(`/api/connection-providers/${providerId}`).then(r => r.json()); 
        const { config } = getData();
        let configRows = [];
        if (Array.isArray(config)) {
          configRows = [...config];
        }
        for (let defaultConfig of provider.config) {
          if (!configRows.some(c => c.key == defaultConfig.key)) {
            addFieldRow({
              path: 'config',
              data: {
                key: defaultConfig.key,
                val: defaultConfig.defaultValue || ''
              }
            })
          }
        }
      }
    })();

  }, [providerId]);
};

export default EnsureConnectionConfigField 


this works well enough for now.

    Open the post
    Continue the discussion in Discord
    Like what we're doing?
    Star us on GitHub!

    Star

    Connect with the Payload Community on Discord

    Discord

    online

    Can't find what you're looking for?

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