Querying with GraphQL
Learn how to query Umbraco Heartcore with GraphQL.
Last updated
Learn how to query Umbraco Heartcore with GraphQL.
Last updated
In this tutorial we will be looking at how we can fetch data from Umbraco Heartcore using GraphQL.
We will be using https://demo.heartcore.dev/ as a reference.
At the end of the tutorial we should be able to use the Umbraco Heartcore GraphQL API and be able to fetch all the content needed to render the page in with a single query.
First, we will need to create some Document Types, and as a start, we will create some element types.
Start by creating a folder named Elements under the Document Types folder in the Settings section of the Backoffice.
In that folder create the following Document Types:
Alias: textAndImage
Add a new group called Content with the following properties:
Title
title
Textstring
Use defaults
Text
text
Rich Text Editor
Use defaults
Image
image
Media Picker
Pick multiple items: not checked Pick only images: checked Disable folder select: checked
Show large image
showLargeImage
Checkbox
Use defaults
Then under permissions check Element Type
Alias: uniqueSellingPoint
Add a new group called Content with the following properties:
Image
image
Media Picker
Pick multiple items: not checked Pick only images: checked Disable folder select: checked
Title
title
Textstring
Use defaults
Text
text
Textarea
Use defaults
Link
link
Multi Url Picker
Max number of items: 1
Then under permissions check Element Type
Then create another folder called Compositions and create the following Document Types in that folder:
Alias: elementsComposition
Add a new group called Elements with the following properties:
Elements
elements
Nested Content
Document Types: Element Type: Text and image, Group: Content, Template: {{title}} Confirm Deletes: checked Show icons: checked Hide label: checked
Then click the Reorder button and change the value for Elements from 0
to 15
Alias: heroComposition
Add a new group called Hero with the following properties:
Image
heroImage
Media Picker
Pick multiple items: not checked Pick only images: checked Disable folder select: checked
Title
heroTitle
Textstring
Use defaults
Subtitle
heroSubtitle
Textstring
Use defaults
Alias: uniqueSellingPointsComposition
Add a new group called Unique Selling Points with the following properties:
Title
uniqueSellingPointsTitle
Textstring
Document Types: Use defaults
Unique Selling Points
uniqueSellingPoints
Nested Content
Document Types: Element Type: Unique Selling Point, Group: Content, Template: {{title}} Confirm Deletes: checked Show icons: not checked Hide label: checked
Then click the Reorder button and change the value for Elements from 0
to 20
At the root create the following Document Types:
Alias: textpage
Click on Compositions and select Elements Composition and Hero Composition
Alias: frontpage
Add a new group called Footer with the following properties:
Title
footerTitle
Textstring
Use defaults
Links
footerLinks
Multi Url Picker
Use defaults
Then click on Compositions and select Elements Composition, Hero Composition and Unique Selling Points Composition, click on Submit.
On the permissions tab check Allow at root and add Textpage to the Allowed child node types property.
Then go to the Content section and create a new Frontpage with the name Home and create some subpages.
The GraphQL endpoint accepts POST
requests with the content type application/json
, the body should be an object containing as a minimum a query
property, for example
For the rest of this tutorial the GraphQL queries are written in plain text that can be executed with the GraphQL Playground.
Lets start with a basic query that fetches the name
, url
, and heroTitle
properties from the Frontpage.
Result:
Up until now, we have been working on a single Document Type. In most cases this is fine, but since we want to dynamically fetch content based on the URL we can use the content
field.
The content
field returns the Content interface type that contains the default fields. To allow us to query the fields on the derived types we can use fragments.
A fragment allows us to query data on the underlying concrete type.
This returns the following JSON:
The query is fetching the name
field which exists on the Content
interface, it also fetches the heroTitle
, heroSubtitle
and heroImage
on the Frontpage
type.
Since the heroImage
is a Media picker we can pass arguments to the url
field telling the server to generate an url with the Image Cropper query string parameters.
There is one problem with our query though. Try changing the url
argument to a subpage and see whats happening.
As you can see we don't get any data back for the hero fields, even though our Document Type has those fields. This is because we are telling GraphQL that we only want them on the Frontpage
type. You might be tempted to fix this by adding another fragment on the Textpage
type which would work, but remember we created a Document Type that only contains hero fields which we have added as a Composition to both the Frontpage
and Textpage
Document Types. We can change the ... on Frontpage
fragment to ... on HeroComposition
and we will now get the expected data back.
Now our query looks like this:
Since Nested Content is an interface named Element
we can query the fields by the specific type using fragments.
Now try to write a query that fetches the title
, text
, link
and image
fields for the Unique Selling Points property.
The only thing we are missing now to be able to render the complete page is the main navigation and the footer.
The main navigation is showing the children of the frontpage, we can fetch them with the following query:
The footer can be fetched using the following query:
We can even combine the two queries into a single query:
In the query above we are also using field aliases, this means that in the response data frontpage
will be named global
and children
will be named mainNavigation
.
You might have noticed that the url
argument is hardcoded in the query. This means that we will always get back the Content for that url. What we want is to pass the argument to the query dynamically.
We can do this by altering the query to include a variable instead of the hardcoded value, this can be done by replacing the argument with $url
and wrapping the query with query($url: String)
.
And then we pass the variable in a separate JSON property called variables
Now that we have all the individual parts we can combine it all into a single query that fetches all the data needed to display the pages on our site:
Variables: