In this article, I will explain what a Rendering Contents Resolver is, and how to use the OOTB Rendering Contents Resolvers in a Sitecore JSS with Next.js solution.
In my previous article Sitecore JSS with Next.js - Creating your first component, we created a component that used the data from the datasource item to render itself. This is the default behavior for a component, the data that is passed to the component by the layout service will be the datasource itself.
However, we come across different requirements for different components. For example:
We can also use the GraphQL API to perform a query and obtain the data needed for our component. However, Sitecore offers an OOTB solution with the possibility to extend, Rendering Contents Resolvers.
You can find the Rendering Contents Resolvers in the path /sitecore/system/Modules/Layout Service/Rendering Contents Resolvers.
The resolvers that Sitecore offers OOTB are as follows:
Here is an example, where we will need to modify the rendering content resolver and use the values in the component.
I have a component called Card List, in which I need to render all the Card items under the Card List. Each card has an image, a heading, a description, and a link.
Create a component named CardListComponent by following the steps mentioned in my previous article.
Add the component created to your page, I will be adding it to a page called demo in my example. Also, add and configure the datasources with some appropriate values.
Go to the rendering item of the component in Sitecore and change the value for the field - Rendering Content Resolver, to Datasource Item Children Resolver. Perform a Publish to clear the layout service cache.
Now, go to the GraphQL Playground and perform a layout query on your page.
query {
layout(site: "JSSProject", routePath: "/demo", language: "en") {
item {
rendered
}
}
}
The output of the query should be similar to the value below:
{
"data": {
"layout": {
"item": {
"rendered": {
"sitecore": {
"context": {
"pageEditing": false,
"site": {
"name": "jssproject"
},
"pageState": "normal",
"language": "en",
"itemPath": "/demo"
},
"route": {
"name": "demo",
"displayName": "demo",
"fields": {
"pageTitle": {
"value": ""
}
},
"databaseName": "web",
"deviceId": "fe5d7fdf-89c0-4d99-9aa3-b5fbd009c9f3",
"itemId": "1a4a3d34-df6a-463f-8b72-58cc56ecc0d4",
"itemLanguage": "en",
"itemVersion": 1,
"layoutId": "aec6b942-174e-581c-a1a0-50aa51432a66",
"templateId": "74e5c244-4fb5-5ae9-bb19-0899d55bf312",
"templateName": "App Route",
"placeholders": {
"jss-main": [
{
"uid": "a52a4929-2ac1-4e8a-9a16-1372465c3ac0",
"componentName": "CardListComponent",
"dataSource": "{6539F816-642F-4B48-B5F7-658ABFE4B676}",
"params": {},
"fields": {
"items": [
{
"id": "8a43ce24-7ba2-4953-8392-8517b0ad5f32",
"url": "/demo/Page-Components/CardListComponent/Card-1",
"name": "Card 1",
"displayName": "Card 1",
"fields": {
"title": {
"value": "GraphQL"
},
"description": {
"value": "GraphQL"
},
"link": {
"value": {
"href": "/en/graphql",
"text": "",
"anchor": "",
"linktype": "internal",
"class": "",
"title": "",
"target": "",
"querystring": "",
"id": "{E507735E-CF6D-57C1-8B02-704027972952}"
}
},
"image": {
"value": {
"src": "https://cm.jssproject.localhost/-/media/System/Email/Placeholders/image300x200.jpg?h=200&iar=0&w=300&hash=2D743D7A0F958598889BE6E80062B606",
"alt": "Placeholder image",
"width": "300",
"height": "200"
}
}
}
},
{
"id": "05917a7f-0b00-4234-91d7-1faf45d5d7c0",
"url": "/demo/Page-Components/CardListComponent/Card-2",
"name": "Card 2",
"displayName": "Card 2",
"fields": {
"title": {
"value": "Styleguide"
},
"description": {
"value": "Styleguide"
},
"link": {
"value": {
"href": "/en/styleguide",
"text": "",
"anchor": "",
"linktype": "internal",
"class": "",
"title": "",
"target": "",
"querystring": "",
"id": "{5F92EEFB-A658-56BA-98B3-0C0B1E6420E2}"
}
},
"image": {
"value": {
"src": "https://cm.jssproject.localhost/-/media/System/Email/Placeholders/image300x200.jpg?h=200&iar=0&w=300&hash=2D743D7A0F958598889BE6E80062B606",
"alt": "Placeholder image",
"width": "300",
"height": "200"
}
}
}
}
]
}
}
]
}
}
}
}
}
}
}
}
Now, we will modify the component definition in the code to match our requirements.
import {
Text,
Field,
withDatasourceCheck,
LinkField,
ImageField,
Link,
Image,
} from '@sitecore-jss/sitecore-jss-nextjs';
import { ComponentProps } from 'lib/component-props';
type CardProps = {
id: string;
fields: {
title: Field<string>;
description: Field<string>;
link: LinkField;
image: ImageField;
};
};
type CardListComponentProps = ComponentProps & {
fields: {
items: CardProps[];
};
};
const CardListComponent = ({ fields }: CardListComponentProps): JSX.Element => (
<div className="container">
<div className="sc-cards">{fields?.items?.map((card) => card && <Card {...card} />)}</div>
</div>
);
const Card = ({ fields, id }: CardProps): JSX.Element => (
<div className="sc-card" key={id}>
<Text field={fields.title} tag="h3" className='h3'/>
<Text field={fields.description} tag="p" />
<Link field={fields.link} className="link-field">
<Image field={fields.image} />
</Link>
</div>
);
export default withDatasourceCheck()<CardListComponentProps>(CardListComponent);
Once you save your changes in the code, your component should render successfully in your rendering host.
References
Happy Sitecoring!