Sitecore MVC Dependent Renderings
This article describes how to include related renderings in Sitecore MVC. Use this for renderings that need a component or script placed on a different area of the page.
The accompanying solution is here. It follows Helix conventions and uses TDS for item serialization. The dependent rendering functionality is defined in a Foundation layer module in the solution. The example renderings with their related components are built as a Feature layer module called "HelloWorld". The basic design of the site (same style as the homepage page in a clean Sitecore install) is defined in the project layer.
In the spirit of keeping things simple, there is no custom build process built into the solution. No need to install Node Package Manager. No need to use 100 different command line tools which will become obsolete next week ;-)
- Create a new Sitecore instance (I built this with Sitecore 8.2 rev. 161115 (Update 1), but you can probably use any 8.x version, but remember to update the NuGet packages).
- Publish each of the modules from Visual Studio (I used Visual Studio 2015).
- Synch the TDS projects.
Why you might need this
To make life easier for content editors.
You have a component (rendering) which will only ever be used in conjunction with another component.
You have a component requiring a script in the head of the page. You don't want to include that script on every page of the site. Or, your script needs data from the datasource of the component.
Don't use this if
- Every page needs the script / related component
- The script is so small it doesn't matter if it's on every page
- You can place the script immediately before or after your component i.e. on the same rendering
How to use
#1 Dependency Placeholder
This is an extension method defining where the dependent renderings can go. You can use it anywhere, but the head of the page, start of body or the end of body are common places. Use dependency placeholder in layouts or renderings.
@using Sitecore.Foundation.DependentRenderings.Extensions @Html.Sitecore().DependencyPlaceholder("head-scripts")
This placeholder is not related to existing placeholder functionality, so it will not be accessible in the Experience Editor and cannot be used for regular renderings. If you also need a regular placeholder in the same place, just add one before or after DependencyPlaceholder call (you can give it the same name).
#2 Main Rendering (has a dependency)
This should use the template
- "Controller Rendering with Dependency" or
- "View Rendering with Dependency"
This rendering works in the same way as a normal controller or view rendering. There is a new field on the rendering definition called "Dependent Renderings". This allows you to select which renderings will be auto-included when this one is used. In every other way, it is the same as a regular controller or view rendering.
#3 Dependent Renderings (the dependency)
These are standard controller or view renderings. The "placeholder" field on the rendering item controls which DependencyPlaceholder is used. The datasource of these renderings is the same as the main rendering.
#4 Add Main Rendering (#2) to presentation details
This is the same as for any other rendering. Just add to the presentation details of your template standard values, or directly to the page. The dependent renderings will then automatically be added to their defined placeholders.
How does it work?
The main work is done starting from the
DependencyPlaceholder extension method in the Foundation module.
- Retrieve all* the Controller/View Rendering with Dependency items under
- Get all the renderings used on the current page (we look at the final presentation details for this).
- From these two collections, find renderings with dependencies on the current page matching the specified placeholder.
- Render the dependent renderings to a string collection.
- Output the concatenated, de-duplicated** string collection as HTML from the extension method.
* Yes, this is not optimal and no, I have not built in any caching mechanism. This was for reasons of clarity/laziness/avoidance of premature optimization ;-) It would probably be best to do the caching at the output HTML level if doing this.
** Prevents duplicate components being output in case two renderings have the same dependency.
Hopefully this module will be of use to someone. If nothing else, it is a simple example of a Helix solution using TDS for item synchronisation.