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?
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.
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
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 😆 )
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-fieldsThanks 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>,
},
@itsjxck love it, the custom component looks great 🙌
This is great, very useful information. Will implement like this, thank you @jesschow and @itsjxck
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.