Can we conditionally change field type based on a sibling value?

default discord avatar
gak4ulast year
4

I have a scenario where user needs to select a field type, based on selection I want to show either a text field or a richText field for a sibling field in the same collection. As of now to make this work, I have 2 fields which I conditionally show/hide based on field type selection.

  • default discord avatar
    chrispy.qlast year

    You could use a custom component from type ui and handle it by yourself as you can access the values from other input fields with the useFields or useFormFields hook.

    https://payloadcms.com/docs/admin/hooks#usefield
  • default discord avatar
    notchrlast year

    @gak4u I think this is what conditions are for and they should work nicely



    Is the condition feature for fields not suitable?



    I imagine you would do something like



            {
              name: "linkUrl",
              label: "Link URL",
              type: "text",
              required: false,
              admin: {
                condition: (data, siblingData, { user }) => {
                  if (siblingData.linkType === "url") {
                    return true;
                  } else {
                    return false;
                  }
                },
              },
            },


    where linkType is a select field type



            {
              name: "linkType",
    
              type: "select",
              hasMany: false,
              defaultValue: "url",
              admin: {
                description:
                  "Select if the Link should go to another page, a PDF, or show a modal with text.",
              },
              options: [
                {
                  label: "Link",
                  value: "url",
                },
                {
                  label: "PDF",
                  value: "pdf",
                },
                {
                  label: "Text",
                  value: "text",
                },
              ],
            },
  • default discord avatar
    gak4ulast year

    This is precisely what I am doing right now, but I am ending up having 2 separate fields to handle both senarios



    [
    {
                  name: "value",
                  type: "text",
                  label: "Value",
                  required: true,
                  admin: {
                    condition: (_, siblingData) => siblingData.type !== 'richText',
                  }
                },
                {
                  name: "rvalue",
                  type: "richText",
                  label: "Value",
                  admin: {
                    condition: (_, siblingData) => siblingData.type === 'richText',
                  }
                },


    But as @Funo suggested, using a custom component will be a better solution



    @Funo Thanks for the suggestion, I will try it out

  • default discord avatar
    kaspartr4 months ago

    I am trying to use the custom component strategy to achieve conditional field types.



    I need to decide the field type based on the selected reference field in the same array.


    The problem is I don't know how to pass sibling data to the custom component. As this is an array, I cannot use the

    getSiblingData()

    as it requires hardcoded field name, which in case of an array, you wouldn't know.



    How would one pass sibling data to custom component.



    My collection:


    ...
      fields: [
                {
                  name: 'attributesArray', // required
                  type: 'array', // required
                  minRows: 0,
                  maxRows: 100,
                  fields: [
                    {
                      type: 'row', // required
                      fields: [
                        {
                          name: 'attribute',
                          type: 'relationship',
                          relationTo: ['attributes'],
                        },
                        {
                          name: 'featureValue',
                          type: 'ui',
                          admin: {
                            components: {
                              Field: () =>
                              FeatureValue({path: name}),
                            },
                          },
                        },
                      ]
                    }
                  ],
                },
              ],
    ...


    FieldType (custom component)



    const FeatureValue: React.FC = (props: { siblingData? }) => {
        // const { value, setValue } = useField<string>({ path })
        const [fields] = useAllFormFields();
        console.log("siblingData: ", siblingData)
    
        return (// return some component);
    };
    
    export default FeatureValue;


    Additional question is how to access the referenced field fields?


    In this example

    : I would need to access the referenced attribute's collection entity field named "dataType" which dictates the field type of the fieldValue field.



    I believe the broader question here is, can one access the referenced entity in another collection "deeply" i.e. can I access all the fields of a referenced entity not just its id,

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.