What about Rendering Parameters?
I recently did a POC using rendering parameters in a component in XM Cloud. In this blog i will describe my approach, issues faced and how i overcame them.
Technologies:
Sitecore XM Cloud
Sitecore Pages Editor
Nextjs components
Create rendering parameters
The datasource for “textColor” is a directory of predefined “Text Color” items.
*Note: One technical draw back with this approach is that selecting an item in a DropLink datasource field retrieves the item ID and not it’s value. More on how I overcame that issue further on.
Front-end Component
For the custom Rich Text component,
-
In Sitecore I cloned the existing Rich Text rendering and renamed it Color Rich Text
-
In the components folder under ../src/MySite/src/components, I copied “Rich Text.tsx” to “Color Rich Text.tsx“
Then we change the code as follows:
import React from 'react'; import { Field, RichText as JssRichText } from '@sitecore-jss/sitecore-jss-nextjs'; interface Fields { Text: Field<string>; } export type RichTextProps = { params: { [key: string]: string }; fields: Fields; }; export const Default = (props: RichTextProps): JSX.Element => { const text = props.fields ? ( <JssRichText field={props.fields.Text} /> ) : ( <span className="is-empty-hint">Rich text</span> ); const id = props.params.RenderingIdentifier; return ( <div className={`component rich-text ${props.params.styles.trimEnd()}`} id={id ? id : undefined} > <div className="component-content"> {text} <style jsx>{` .component-content { background-color: ${props.params.textColor ? props.params.textColor.trimEnd() : '#FFF'}; } `}</style> </div> </div> ); };
Here we are expecting the value of the parameter textColor
to be sent in the props of the component as props.params.textColor
.
Now that these pieces are in place, I added this component to a page via regular Sitecore Experience Editor.
Connecting Pages Editor to your local
Next I connected the XM Cloud Pages Editor to my local environment by adding this entry in “Local Storage” in your browser and navigate to https://pages.sitecorecloud.io/
"Sitecore.Pages.LocalXmlCloudUrl": "https://xmcloudcm.localhost/"
Now we refresh the pages editor
As we can see the pages editor displays the items in the DropLink correctly, so i can select the color. So the field shows up in pages editor, however the selected color is not applied. Lets check the graphQL playground to see what is data getting sent.
See in graphQL playground:
So we see the field “textColor” coming through as a parameter, however the value is the Item ID of the selected color item, not the value. How do we overcome this hurdle?
Research and solution
I found this article by from Any Paz
-
-
I created a data template that governs serialization of an item in Sitecore. This way I can determine what i want serialized.
-
I created a custom pipeline processor and override the existing RenderJsonRendering.Initialize pipeline to extend it to serialize only the item flagged in Sitecore to serialize.
-
I made these two modifications generic enough to apply wider use-cases for custom serializing custom rendering parameters.
using System.Collections.Generic; using Sitecore.Data; using Sitecore.Data.Items; using System.Web; using Sitecore.Abstractions; using Sitecore.LayoutService.Configuration; using Sitecore.LayoutService.ItemRendering; using Sitecore.LayoutService.Presentation.Pipelines.RenderJsonRendering; using Sitecore.XA.Feature.LayoutServices.Integration.Pipelines.TransformParameters; using System.Linq; using Newtonsoft.Json.Linq; using Sitecore.Mvc.Presentation; using System; using Sitecore.LayoutService.Serialization; namespace MySite.Foundation.LayoutService.PipelineProcessors { public class CustomInitialize : Initialize { IRenderingConfiguration _renderingConfiguration; protected BaseCorePipelineManager PipelineManager; public CustomInitialize(IConfiguration configuration, BaseCorePipelineManager pipelineManager) : base(configuration) { PipelineManager = pipelineManager; } protected override RenderedJsonRendering CreateResultInstance(RenderJsonRenderingArgs args) { string componentName = base.GetComponentName(args.Rendering?.RenderingItem?.InnerItem); _renderingConfiguration = args.RenderingConfiguration; //Note: the constructor below is different for Sitecore 9.x and 10. The below will only work in Headless Services for Sitecore 10. RenderedJsonRendering rendering = new RenderedJsonRendering { ComponentName = componentName ?? args.Rendering.RenderingItem.Name, DataSource = ((!string.IsNullOrWhiteSpace(args.Rendering.DataSource)) ? args.Rendering.DataSource : args.Rendering.RenderingItem.DataSource), RenderingParams = SerializeRenderingParams(args.Rendering), Uid = args.Rendering.UniqueId }; TransformParametersArgs transformParametersArgs = new TransformParametersArgs { Rendering = rendering }; transformParametersArgs.CustomData.Add("SupportedParameters", GetAllKeys(args.Rendering.Properties["par"])); PipelineManager.Run("transformParameters", transformParametersArgs); return transformParametersArgs.Rendering; } protected virtual IDictionary<string, string> SerializeRenderingParams(Rendering rendering) { IDictionary<string, string> paramDictionary = rendering.Parameters.ToDictionary(pair => pair.Key, pair => pair.Value); foreach (string key in paramDictionary.Keys.ToList()) { if (!ID.TryParse(paramDictionary[key], out var itemId)) continue; Item item = rendering.RenderingItem.Database.GetItem(itemId); //Check if serializable if (item.Fields["SerializeItem"]!=null && item.Fields["SerializeItem"].Value == "1") { paramDictionary[key] = JObject.Parse(_renderingConfiguration.ItemSerializer.Serialize(item, new SerializationOptions() { DisableEditing = true }))["Value"]?.Value<string>("value"); } } return paramDictionary; } protected virtual string[] GetAllKeys(string par) { if (string.IsNullOrEmpty(par)) { return Array.Empty<string>(); } List<string> list = new List<string>(); string[] array = HttpUtility.UrlDecode(par).Split('&'); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split('='); if (array2.Length != 0) { list.Add(array2[0].Trim()); } } return list.ToArray(); } } }
A quick patch into the pipeline
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <pipelines> <group groupName="layoutService"> <pipelines> <renderJsonRendering> <processor type="MySite.Foundation.LayoutService.PipelineProcessors.CustomInitialize, MySite" resolve="true" patch:instead="*[@type="Sitecore.XA.Feature.LayoutServices.Integration.Pipelines.RenderJsonRendering.Initialize, Sitecore.XA.Feature.LayoutServices.Integration"]"/> </renderJsonRendering> </pipelines> </group> </pipelines> </sitecore> </configuration>
Now, when I look at the results coming back in the graphQL playground, we see the value returned
Now looking at the pages editor we see something interesting
Pages editor is a live editor, therefore we see the color change immediately once we select the parameter.
In the live site we see our desired result:
This was an interesting POC, and I hope to uncover more useful case-studies and POCs from the new offering of Sitecore XM Cloud.
Until next time, stay curious!