Like what we’re doing? Star us on GitHub!

How to access relationship field full item data?

KasparTr
last month
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?

  • jesschow
    Payload Team
    4 weeks 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.

  • jmikrut
    Payload Team
    4 weeks 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

  • itsjxck
    4 weeks 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 😆 )

  • jesschow
    Payload Team
    4 weeks 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
  • itsjxck
    4 weeks 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>,
    },
  • jesschow
    Payload Team
    4 weeks ago

    @itsjxck love it, the custom component looks great 🙌

  • KasparTr
    4 weeks ago

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

Open the post
Continue the discussion in Discord
Can't find what you're looking for?
Get help straight from the Payload team with an Enterprise License.Learn More