Ok, here is something completely experimental. Consider the following real world example from . You have a section called “” and you have a left rail where the leftnav typically sits. Now your marketers want the “call-to-action” rendering to be placed below the leftnav:
…and what’s important, have it cascade to all child pages (). let’s take this as an example
Pretty interesting scenario, heh?
Now let’s take the latest Sitecore 6.5.0 and get it done. The thought process is the following. Let’s find a place where Sitecore assembles the page dynamically, and look out for a way to inject our “call-to-action” rendering based on our business rules.
First place to look is the <insertRenderings /> pipeline introduced in 6.4. Before that all the page assembly magic was happening within <renderLayout /> pipeline.
The _<insertRenderings /> _pipeline looks like this:
<processor type="Sitecore.Pipelines.InsertRenderings.Processors.GetItem, Sitecore.Kernel" />
<processor type="Sitecore.Pipelines.InsertRenderings.Processors.AddPageDesignerRenderings, Sitecore.Kernel" />
<processor type="Sitecore.Pipelines.InsertRenderings.Processors.AddRenderings, Sitecore.Kernel" />
<processor type="Sitecore.Pipelines.InsertRenderings.Processors.EvaluateConditions, Sitecore.Kernel" />
</insertRenderings>There is a processor called “AddRenderings”, so why don’t we create our own, pasted it below it and “enrich” the rendering collection based on our custom logic and call it “AddCascadedRenderings”:
1: public class AddCascadedRenderings : InsertRenderingsProcessor
3: public override void Process(InsertRenderingsArgs args)
5: Assert.ArgumentNotNull(args, "args");
6: if (args.ContextItem null) return;
8: var device = Context.Device;
9: if (device null) return;
11: if (Context.Site.Name != "website") return;
13: if (args.ContextItem.Parent null) return;
15: var parentRenderings = args.ContextItem.Parent.Visualization.GetRenderings(device, true);
17: var cascadedRenderings = parentRenderings.Where(rendering => rendering.Settings.Cascaded());
21: }Remember that this is quite an experimental prototype code, so we are going to skip all safety and boundary checks. Basically what we are doing here is: 1. getting the renderings from the parent item on line 15. 2. filtering out the rendering collection from the parent item to have only those renderings that are set as “cascaded” on line 17. This is an extension method that will be demonstrated later. 3. adding the “cascaded” renderings to the arguments. The aforementioned extension method is fairly simple, it’s reading the parameters passed on to the rendering and checks for “cascade” checkbox value:
1: public static bool Cascaded(this RenderingSettings settings)
3: var parameters = WebUtil.ParseQueryString(settings.Parameters);
4: return parameters != null && parameters["cascade"] "1";
This obviously means that we need to have a custom “Parameters Template” specified for our “call-to-action” rendering, which would give us ability to have similar experience in Page Editor:
The last thing would be to disable the rendering from being editable on child pages, but I would leave that for the next post.
Here is the result of our actions: