Well, I have a Content Type "basic page" (a classic) and inside I can use Layout Builder to put in some custom blocks with fields. For this case I need to reach values from a certain block "FactBox" and some of its fields: title, subtitle, body...you know. But I have to get values from an entity reference field too. I have a media field for uploading documents "listOfDocuments" (name of type: MediaPdf), and I need to send to the frontend layer name of the file, url, the internal uri... How can I get the values? this is the use case here.
As you can see, I'm trying to reach values from fields: uri, url, name
of a media entity MediaPdf
in a field ListOfDocuments
included on a block called MyCustomBlock
which is present in the main
zone of Layout Regions
inside a Content Type Page
and we're testing the query against a specific node with url /basic-page
. Along the way, I will take advantage and get other field values included in the custom block: title, subtitle, text
, just before the ListOfDocuments
field.
query MyQuery {
route(path: "/basic-page"){
... on Page {
id
layoutRegions {
main {
block {
... on MyCustomBlock {
title
subtitle
text
listOfDocuments {
uri
url
name
}
}
}
}
}
}
}
}
For contex, there are the description of the components I'm using as I have described in .graphqls files:
The main block:
"My Custom block component"
type MyCustomBlock implements BlockContentInterface {
"User-entered Headline."
title: String
"User-entered Sub Headline."
subtitle: String
"User-entered text, contains formatted HTML."
text: String!
"An array of document collection items"
listOfDocuments: [MediaPdf]
"UUID of the block. Useful for keying."
uuid: String!
}
The Media field for documents:
type MediaPdf implements MediaInterface {
uuid: String!
uri: String
url: String
name: String
}
I need to add a new method addMediaPdfFieldResolver(ResolverRegistryInterface $registry, ResolverBuilder $builder)
in a Schema description file.
$registry->addFieldResolver('MediaPdf', 'name',
$builder->produce('entity_label')
->map('entity', $builder->fromParent())
);
$registry->addFieldResolver('MediaPdf', 'uri',
$builder->compose(
$builder->produce('entity_url')
->map('entity', $builder->fromParent()),
$builder->produce('url_path')
->map('url', $builder->fromParent())
));
If you use something like:
$registry->addFieldResolver('MediaPdf', 'url',
$builder->produce('entity_url')
->map('entity', $builder->fromParent())
);
You will get an error while debugging your Query:
"Expected a value of type \"String\" but received: instance of Drupal\\Core\\Url"
This happens due to the use of the toURL()
method, that returns an URL Object and not a String, as GraphQL is waiting. See api.drupal.org/function/EntityBase::toUrl/9.2.x. Using $builder->fromParent()->toString()
is not an option either, it won't work.
So you have to look for another resources... you can use composing from a resource from the Image data producers, for instance. Let's see:
$registry->addFieldResolver('MediaPdf', 'url',
$builder->compose(
$builder->produce('property_path')
->map('type', $builder->fromValue('entity:media'))
->map('value', $builder->fromParent())
->map('path', $builder->fromValue('field_media_file.entity')),
$builder->produce('image_url')
->map('entity', $builder->fromParent())
->map('field', $builder->fromValue('field_media_file'))
)
);
{
"data": {
"route": {
"id": "3",
"layoutRegions": {
"main": [
{
"block": {
"title": "Title of my custom block",
"subtitle": "Subtitle for my custom block",
"text": "<p>Lorem fistrum diodeno jarl está la cosa muy malar.</p>",
"listOfDocuments": [
{
"uri": "/media/4/edit",
"url": "https://my.domain.site/sites/default/files/2021-09/gramenawer.pdf",
"name": "gramenawer.pdf"
},
{
"uri": "/media/3/edit",
"url": "https://my.domain.site/sites/default/files/2021-09/benemeritaar.pdf",
"name": "benemeritaar.pdf"
}
]
}
}
]
}
}
}
}
It works! now I'm getting the related values!
@davidjguru how did you get the layout builder item to expose?