I think each Sitecore developer knows that there are two possible ways to manage item's presentation components (renderings and sublayouts):
- The Experience Editor
- The Content Editor
The Experience Editor is really an effective tool for managing item content and list of renderings, but Experience Editor does not work for all sites and all pages. Also it is not the fastest way to add a single component because loading the EE takes some time.
The second way, the Content Editor, allows us to add renderings and sublayouts faster. Unfortunately, it is less comfortable because we need to know the exact placeholder's name to which we want the rendering to be added. Also, the lists of allowed renderings and sublayouts are unlimited and we have to look for the necessary component through all renderings and sublayouts defined in Sitecore:
I’ve been working with Sitecore for about five years; and I was always thinking how comfortable it would have been to have a list of placeholder’s names in which selected rendering or sublayout can be used. I decided to implement such a solution myself.
Recommended Rendering Module provides a list of recommended renderings that potentially can be used with current item and the collection of placeholder names where selected rendering can be added:
Module implementation can be logically divided into two parts: preparation of the list of renderings and the list of placeholders.
Implementation of both parts is based on the lucene search index which contains the following types of items:
- Content items (/sitecore/content by default)
- Placeholder Settings (/sitecore/layout/Placeholder Settings by default)
First, the index with two location for paths was configured:
But during testing there was an issue with updating nodes from the second location. After spending some time for investigation I found out the article (http://sitecore.stackexchange.com/questions/3480/issue-with-multiple-crawlers-on-solr-custom-search-index) where this issue was described. Sitecore was able to provide a patch for the SitecoreItemCrawler class. It doesn't appear to be on their Github so I can't link it but I asked for support DLL 108165. The issue is fixed in Sitecore 8.2 Update 1. I didn’t want to trouble module user by any updates of sitecore and prepared two configurations: with single index and two locations configured and with two indexes where each of them was configured for one location. By default, the module is configured for using two indices as this configuration definitely work with all versions of sitecore. Please, make sure you have downloaded an appropriate version of module.
Index includes just two fields “Allowed Controls” and “Placeholder Key” of the Placeholder template and one computed field that prepares a list of renderings that are used on the item. It’s enough for us to get necessary data for building module.
The list of recommended renderings is based on the renderings that are already used with current item plus renderings that are used on the items with the same template. Each of them are already assigned to some placeholders. I’ve prepared a list of placeholders and found the renderings that are specified for these placeholders in the Placeholder Settings. After that I can extend the recommended renderings list with newly found placeholders. This way, a rendering will be included into the recommended list in several cases:
- a rendering is already used on an item;
- a rendering is already used on an item with the same template;
- a rendering is specified for placeholder that is presented on the item;
The list of recommended placeholders is prepared for selected rendering (on the original control or on the recommended rendering). I look for all items where this rendering is used and get placeholders from there + find the placeholder settings that included the selected rendering and extend the list with it.
As a result, we have two lists that should be shown to the users and it is not less complicated. Sitecore has the TreeviewEx control that is used on the Select Rendering dialog. But the control can process only items from Sitecore’s root, it can’t work with virtual items and it doesn’t match my requirements because the data I want to display comes from the search index. The solution was to implement custom control (RecommendedRenderingTreeview) that have the same behavior with the Sitecore TreeviewEx. In order to add the new control to the Select Rendering dialog, I had to override it. The most correct way to do that it is to put the custom SelectRendering.xml (code is here: CustomSelectRendering.cs) to the override folder by the following path:
So the RecommendedRenderingTreeview is added to the SelectRendering.xml and the last thing I needed was to pass a current item’s ID from the SelectRendering dialog to the custom treeview. After investigation I haven’t found any way to get the current ID from the SelectRendering dialog. I decided to override the DeviceEditor.xml (code is here: CustomDeviceEditor.cs) dialog and pass the current item ID to SelectRendering by query string parameter. If you know a better way - please let me know.
When we select any rendering, we call the SelectableItemPreview_Click method to prepare the recommended placeholders list. And to display the prepared list we add RecommendedPlaceholders.js and RecommendedPlaceholders.css
The module has three configuration files:
- RecommendedRenderings.config - includes a general settings of module and contains the following settings:
- ContentRootPath - Recommended Renderings will be shown just for the selected root item and his children. It is better to specify a content root which you currently work with. It will reduce a time of rebuild index and preparing the recommended renderings list. Default value: /sitecore/content
- DatabaseName - Determines the database that is used by the Recommended Renderings module to prepare the list of recommendations. It have to be the same database which is configured for the "recommended-renderings-index" index. Usually it is "master" and wouldn't be changed. Default value: master
- IsExpandedDefault - If true, the Recommended Renderings tree will be expanded by default. Default value: false
- PlaceholderSettingsRootPath - Recommended placeholders list will be shown just for the selected root item and his children. It is better to specify a content root which you currently work with. It will reduce a time of rebuild index and preparing the recommended placeholders list.
Default value: /sitecore/layout/Placeholder Settings
- TreeviewRootIcon - Default icon for root element of the recommended renderings list. Default: Applications/16x16/windows.png
- Z.RecommendedRenderings.ContentSearch.Configuration.config - defines a search index configuration. It’s different for each of versions of Sitecore and should not be changed.
- Z.RecommendedRenderings.ContentSearch.Index.config - defines a search index. It’s also different for each of versions of Sitecore. The Crowling locations should be the same with pathes that defined in the ContentRootPath and PlaceholderSettingsRootPath settings of RecommendedRenderings.config
WARNING: The module will override the Sitecore’s default SelectRendering and EditDevice dialogs. You always will be able to restore them if needed (see the Uninstall section). BUT make sure that you haven’t already overridden this dialogs on your environment. If so, we do not recommend to install the module. Please contact me in this case and we will solve it individually.
Follow the steps below for installing module:
- Make sure that you downloaded the correct version of the module.
- Install downloaded package using installation wizard.
Optional Step. The install package has a post install step that should rebuild the index automatically, but if in case module doesn't work after installation, you need to rebuild index manually:
- Go to the Index Manager and build the following indexes: recommended-renderings-index and recommended-placeholders-index NOTE: If you use the Sitecore v.8.2 or earlier version, you will need to build just recommended-renderings-index.
If you don’t like the module or in some other reasons you want to uninstall the module, remove files by the following paths: