Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

How to access relationship field full item data?

default discord avatar
kaspartr2 years ago
7

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?

  • default discord avatar
    jessrynkar2 years 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
    2 years ago

    Bit more info here - yes,

    @567578449439621124

    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
    itsjxck2 years ago

    Hi

    @364124941832159242

    , 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 😆 )

  • default discord avatar
    jessrynkar2 years ago

    Hey

    @93699784942034944

    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
    itsjxck2 years ago

    Thanks for the examples

    @854377910689202256

    , 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,
            },
          },
        },


    @567578449439621124

    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>,
    },
  • default discord avatar
    jessrynkar2 years ago
    @93699784942034944

    love it, the custom component looks great 🙌

  • default discord avatar
    kaspartr2 years ago

    This is great, very useful information. Will implement like this, thank you

    @854377910689202256

    and

    @93699784942034944
Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.