I was playing around with Placeholder Settings, and thought it would be a nice topic for my next blog post – especially since I wanted to customize it a bit.
Adding placeholder settings
Placeholder settings can be added in different ways. The placeholder settings items are saved in the /sitecore/layout/Placeholder Settings folder.
The ‘global’ placeholder settings need a placeholder settings item to be created, then assigned a placeholder key (which needs to match the placeholder key in the sublayout) and can be assigned its allowed controls.
Another way is to add placeholder settings on the Layout details. The placeholder settings item will end up in the Placeholder Settings folder, but will not have a Placeholder Key set in the item itself. It will be bound to a placeholder on the layout.
Now, I had an article page, on which people could leave their comments through a Comment widget. This widget is enabled on some articles, but Content Editors can also remove it if they don’t want this functionality. This means they’d also have to be able to add it back again if they’ve removed it and changed their minds later – but I only want it on the page once, since it doesn’t make too much sense to have the same widget on the page twice.
When looking in the Core database (We can see all things Page Editor in /sitecore/content/Applications/WebEdit/Ribbons/WebEdit), we can see which command gets triggered by clicking the ‘new component’ button:
Using the Commands.config file, this translates to the following command:
<command name=“webedit:addrendering” type=“Sitecore.Shell.Applications.WebEdit.Commands.AddRendering,Sitecore.Client“/>.
In the AddRendering class there’s a private static void defined called RunGetPlaceholderRenderingsPipeline, which kicks off a pipeline like this:
If we then look in the web.config and see what the getPlaceholderRenderings pipeline does:
<processor type=“Sitecore.Pipelines.GetPlaceholderRenderings.GetAllowedRenderings, Sitecore.Kernel“/>
<processor type=“Sitecore.Pipelines.GetPlaceholderRenderings.GetPredefinedRenderings, Sitecore.Kernel“/>
<processor type=“Sitecore.Pipelines.GetPlaceholderRenderings.RemoveNonEditableRenderings, Sitecore.Kernel“/>
<processor type=“Sitecore.Pipelines.GetPlaceholderRenderings.GetPlaceholderRenderingsDialogUrl, Sitecore.Kernel“/>
The easiest solution would then be to add a processor to the pipeline.
A processor needs a Process method, and in our case will expect GetPlaceholderRenderingsArgs as well.
I figured I would start off simple and just make it so I can’t add any control to the placeholder if that control is already there.
Here’s the code I wrote for this:
publicvoid Process(GetPlaceholderRenderingsArgs args)
List<Item> placeholderRenderings = args.PlaceholderRenderings;
if (placeholderRenderings != null)
placeholderRenderings.RemoveAll(x => args.LayoutDefinition.Contains(x.ID.ToString()));
Relatively easy – go get PlaceholderRenderings, remove all renderings that are already in the LayoutDefinition. Note that this means we can now only have the control once per page as we are looking at the complete LayoutDefinition and not just the controls added to a specific placeholder.
Then I added my processor before
<processor type=“Sitecore.Pipelines.GetPlaceholderRenderings.GetPlaceholderRenderingsDialogUrl, Sitecore.Kernel“/> in the <getPlaceholderRenderings>node
in the <getPlaceholderRenderings> node:
<processor type=“TestApplication.PlaceholderSettingsTest, TestApplication“/>
I then set up my page. In my page I can add either Random Sublayout or Random Rendering.
I added Random Rendering to the page, so I would expect Random Sublayout to be the only addable control.