How to access relationship field full item data?

default discord avatar
KasparTr
7 months ago
9

I must conditionally populate collection fields based on the selected relationship field. The relationship field only provides the ID of the selected item. As the admin fields don't support async functions, there is no way to query more information about the selected item before updating other collection fields.



Is there some workaround to access the selected item data and based on that, alter other fields via admin config like condition?

  • discord user avatar
    jesschow
    Payload Team
    7 months ago

    Have you defined

    maxDepth

    on your relationship field? You should be able to return the full data from your relationship.



    And then yes, you will be able to use hooks to populate the other fields in your collection.

  • discord user avatar
    jmikrut
    Payload Team
    7 months ago

    Bit more info here - yes, @KasparTr as you mentioned, conditional logic is not async intentionally. This is because those functions run VERY often, and should be heavily optimized. You could however have a "virtual" field with a custom React field component, that stores the data you need from the selected relationships. Your virtual field would simply fetch the relationship data, and return the relationship values that you need - but NOT store those values in the database. Rather, just show them. Then, that virtual field would be visible in the condition, which you could at that point use

  • default discord avatar
    itsjxck
    7 months ago

    Hi @jmikrut, thanks for the extra info on this. Would it be possible to get an example of how you think this might work? I'm struggling to wrap my head around how to achieve this (maybe I'm thinking about it in a more complicated way than needs be, or maybe I just need more coffee 😆 )

  • discord user avatar
    jesschow
    Payload Team
    7 months ago

    Hey @itsjxck checkout this demo of virtual fields, specifically look at the

    nextEvent

    field in the

    Locations

    collection - you would want to add something similar to this

    https://github.com/payloadcms/payload/tree/master/examples/virtual-fields
  • default discord avatar
    itsjxck
    7 months ago

    Thanks for the examples @jesschow, much appreciated! Unfortunately this didn't seem to work for me as I needed the editor to dynamically update with this value during edit, and the hooks didn't seem to run while actively editing the document. I did get a solution working, although it may not be the cleanest, by using a custom UI component:


    import React, { useEffect } from "react";
    import { useField } from "payload/components/forms";
    import { RelationshipField, UIField } from "payload/types";
    import { useDocumentInfo } from "payload/components/utilities";
    
    const RelationExpansion: React.FC<UIField> = ({ name }) => {
      const refFieldName = name.replace("_", "");
    
      const {
        collection: { fields },
      } = useDocumentInfo();
    
      const relationField = fields.find(
        (field) => field.type === "relationship" && field.name === refFieldName
      ) as RelationshipField;
    
      const { value: self, setValue: setSelf } = useField({ path: name });
      const { value: ref } = useField<string>({
        path: refFieldName,
      });
    
      useEffect(() => {
        if (!ref) return;
    
        const getRelation = async () => {
          try {
            const relationFetch = await fetch(
              `/api/${relationField.relationTo}/${ref}`
            );
    
            const relation = await relationFetch.json();
    
            setSelf(relation);
          } catch (error) {
            console.log(error);
          }
        };
    
        getRelation();
      }, [ref]);
    
      return (
        <code style={{ display: "none" }}>
          {JSON.stringify({ relationField, ref, self })}
        </code>
      );
    };
    
    export default RelationExpansion;


    In my collection I can use this to expand the relation, using an underscore to prefix the name of the field i want to expand:


        {
          name: "type",
          type: "relationship",
          relationTo: ItemTypes.slug,
          hasMany: false,
          required: true,
        },
        {
          name: "_type",
          type: "ui",
          admin: {
            components: {
              Field: RelationExpansion,
            },
          },
        },


    @KasparTr assuming you have a similar usecase to myself, this might also work for you; you can then use this field in conditionals:


    admin: {
      condition: (data) => data._type?.<field_on_relation>,
    },
  • discord user avatar
    jesschow
    Payload Team
    7 months ago

    @itsjxck love it, the custom component looks great 🙌

  • default discord avatar
    KasparTr
    7 months ago

    This is great, very useful information. Will implement like this, thank you @jesschow and @itsjxck

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.