I did the following experiment: created collection with one field - text field and set this field as title. I created another collection with one field - relationship - and linked to first collection. I added some data and saw field values to select. I set a title as this field for this collection. I created 3rd collection and added one field - relationship - and linked to collection 2. When I started adding data, I saw just payload IDs in place of field values. This is what are users are complaining about. They want to see field values not IDs. Is that by design or we could do some trick to fix that.
If i got you right i think depth is your answer
We are not running any queries at this point - we just use Payload CMS UI to enter a data for collection that we created.
Hey
@956827460975083550- if I understand correctly, you could use a virtual field to get specific data for your doc title.
So in your case, you have 3 collections.
-
CollectionOne
- w/ text field set as title
-
CollectionTwo
- relationship to
CollectionOne
-
CollectionThree
- relationship to
CollectionTwo
In order for
CollectionThree
to see field values, in your
CollectionTwo
you'd create a virtual field that looks like this:
{
name: 'title',
type: 'text',
admin: {
hidden: true
},
hooks: {
beforeChange: [
async ({ data }) => {
const req = await fetch(`${process.env.URL}/api/collectionOne/${data.relationshipOne.value}`)
.then(res => res.json())
.then(data => {
return data.title
})
return req
}
]
}
},
You would then set
useAsTitle: 'title'
relationshipOne
in this case, is the name of the relationship field in this collection (CollectionTwo)
Now that CollectionTwo should have titles, CollectionThree should be seeing those titles instead of IDs
Let me know if this makes sense or if you need any help!
Unfortunalty. it does not work. After looking at virtual-fields example, i got like that:
const slugName = 'linkedField';
const getTitleToUse: FieldHook = async (args) => {
const {
value,
req,
} = args;
const linkedItem = await payload.find({
collection: 'DefaultLocalizedText',
locale: req.locale,
where: {
id: { equals: value },
},
});
return linkedItem.docs[0].LocalizedText;
};
const LocalizedTextLinkedCollection1: CollectionConfig = {
slug: slugName,
admin: {
useAsTitle: slugName,
},
access: {},
fields: [
{
name: slugName,
type: 'relationship',
relationTo: 'DefaultLocalizedText',
maxDepth: 0,
hooks: {
afterRead: [
getTitleToUse,
],
},
},
],
};
However, I am getting the following server side error:
As I understand for relationship field I am trying to display a string as a title, but it is looking for ObjectId.
This is what I see at the screen:
Did anybody try doing something like that or this is just first attempt? 🙂
Thanks again for your message!
Yes, others are using this same method. Check this link out:
https://payloadcms.com/community-help/discord/useastitle-a-field-not-id-from-a-relationshipThe example I provided for you is a working example, did you give that a shot?
I will look into your example shortly and see what's going on
This code is not related to relationship field, it is for text field:
{
name: 'title',
type: 'text',
admin: {
hidden: true,
},
hooks: {
beforeChange: [
({ data }) => {
return data.course.title;
}
],
},
}
Or, this is just a virtual field that is not seen
Yes, this is the virtual field.
The above
text
field simply acts as the
title
for your documents in your 2nd collection (w/ relationship field) - that way when your 3rd collection is a relationship to
collectionTwo
, you won't just see IDs
wow - this is what I missed - let me try, thank you very much for your help!
No problem! I'm here if you have any other questions!
Thanks again for all your help - but I am having really weird problem when I am trying from CollectionThree select value from CollectionTwo:
I see the following crash
Did you guys saw anything like that?
Can you show me what your collection configs look like?
I was able to repro with the following collections:
import { CollectionConfig } from 'payload/types';
const DomainCollection: CollectionConfig = {
slug: 'domains',
labels: {
singular: 'domain',
plural: 'domains',
},
admin: {
useAsTitle: 'domain',
},
access: {},
fields: [
{
name: 'domain',
type: 'text',
}
],
};
export default DomainCollection;
import { CollectionConfig } from 'payload/types';
const RegionCollection: CollectionConfig = {
slug: 'regions',
labels: {
singular: 'region',
plural: 'regions',
},
admin: {
useAsTitle: 'region',
},
access: {},
fields: [
{
name: 'region',
type: 'text',
}
],
};
export default RegionCollection;
import { CollectionConfig } from 'payload/types';
const DomainsregionsCollection: CollectionConfig = {
slug: 'domainsregions',
labels: {
singular: 'domainsregions',
plural: 'domainsregions',
},
admin: {
useAsTitle: 'domainsregions',
},
access: {},
fields: [
{
name: 'domainsregions',
type: 'relationship',
relationTo: ['domains', 'regions'],
hasMany: true,
}
],
};
export default DomainsregionsCollection;
If I am removing asTitle from DomainsregionsCollection, it is not crashing
Hey
@956827460975083550- I went ahead and updated your collections to get this working:
import { CollectionConfig } from 'payload/types';
const DomainCollection: CollectionConfig = {
slug: 'domains',
labels: {
singular: 'domain',
plural: 'domains',
},
admin: {
useAsTitle: 'domain',
},
access: {
read: () => true,
update: () => true,
create: () => true,
},
fields: [
{
name: 'domain',
type: 'text',
},
],
}
export default DomainCollection;
import { CollectionConfig } from 'payload/types';
const RegionCollection: CollectionConfig = {
slug: 'regions',
labels: {
singular: 'region',
plural: 'regions',
},
admin: {
useAsTitle: 'region',
},
access: {
read: () => true,
update: () => true,
create: () => true,
},
fields: [
{
name: 'region',
type: 'text',
admin: {
hidden: true
},
hooks: {
beforeChange: [
async ({ data }) => {
const req = await fetch(`${process.env.URL}/api/domains/${data.relationshipOne.value}`)
.then(res => res.json())
.then(data => {
return data.domain
})
return req
}
]
}
},
{
name: 'relationshipOne',
type: 'relationship',
relationTo: ['domains'],
access: {
read: () => true,
update: () => true,
create: () => true,
}
},
],
}
export default RegionCollection;
import { CollectionConfig } from 'payload/types';
const DomainregionsCollection: CollectionConfig = {
slug: 'domainregions',
fields: [
{
name: 'RelationshipTwo',
type: 'relationship',
relationTo: ['regions'],
maxDepth: 2,
},
],
}
export default DomainregionsCollection;
Couple things to note:
-
DomainCollection
didn't require any changes
-
RegionCollection
- This has a relationship field with a relationTo
domains
, I also added the virtual field here called
region
, it has a
beforeChange
hook that fetches the
title
of the domains doc you are doing a relation to. This way, the title of this document becomes the title of the
DomainsCollection
document we have a relationship with.
-
DomainregiosnCollection
- this simply has a
relationship
field to the
regions
collection. Now when you look at values in this collection, you will see titles instead of IDs
Let me know if this makes sense or need any further explanation.
Yes and if you set admin: {
useAsTitle: ''RelationshipTwo",
}, for DomainregionsCollection, it has client side crash . Everything else is working, we did it a little different for virtual field, but this is not about that.
If you put like that relationTo: 'regions', it is not crashing
When I put for you those 3 collections, I made that very simple to be able to just to run locally and see a client side crash
Setting
useAsTitle
to
RelationshipTwo
will cause a crash because a relationship field returns an object of data, not a value.
useAsTitle
needs to be a value.
So in order for the above to work, you'd need to create another virtual field in the
DomainregionsCollection
, similar to what you are doing in the
RegionCollection
Or just use like that: relationTo: 'regions'
It works 😉
Thank you very much!
No problem
Star
Discord
online
Get dedicated engineering support directly from the Payload team.