Dynamic placeholders
When you use dynamic placeholders, you can add the same placeholder name several times. You can do this across multiple renderings, and you can even use the same placeholder multiple times in a single rendering.
Dynamic placeholders mean that:
- Unique keys are guaranteed across different renderings and within one rendering.
- You can build functionality that generates multiple placeholders within the same rendering dynamically.
Using dynamic placeholders
The DynamicPlaceholder extension method is available in the SitecoreHelper class in the Sitecore.Mvc.Helpers namespace. The method has several overloads:
-
DynamicPlaceholder(string placeholderName, int count = 1, int maxCount = 0, int seed = 0)placeholderName- the name of the placeholder. It must be a non-empty string.count- specifies how many placeholders Sitecore renders. It must be a non-negative number.maxCount- the upper limit of the number of dynamically generated placeholders. It must be a non-negative number.seed- a number used to calculate a starting value of a generated placeholder key suffix. It must be a non-negative number.
@Html.Sitecore().DynamicPlaceholder("content"/*, optional parameters*/)
-
DynamicPlaceholder(string placeholderName, TagBuilder chrome, int count = 1, int maxCount = 0, int seed = 0)chrome- theTagBuilderobject that specifies the HTML tag that will wrap eachcountof all dynamically generated placeholders. -
DynamicPlaceholder(string placeholderName, Func<DynamicPlaceholderRenderContext, TagBuilder> chromeResolver, int count = 1, int maxCount = 0, int seed = 0)chromeResolver- the function that generates individual aTagBuilderwrapper for a specific dynamic placeholder, based onDynamicPlaceholderRenderContext. -
DynamicPlaceholder(string placeholderName, Func<HtmlString, HtmlString> outputModifier, int count = 1, int maxCount = 0, int seed = 0)outputModifier- the function that accepts the HTML output of a specific placeholder and returns the modified HTML. -
DynamicPlaceholder(string placeholderName, Func<HtmlString, DynamicPlaceholderRenderContext, HtmlString> outputModifier, int count = 1, int maxCount = 0, int seed = 0)outputModifier- the function that accepts the HTML output of a specific placeholder,DynamicPlaceholderRenderContext, and returns the modified HTML. -
DynamicPlaceholder(DynamicPlaceholderDefinition definition)definition- aggregates all options for defining a dynamic placeholder
Unlike a regular Sitecore placeholder that uses a placeholder name as a placeholder key, a dynamic placeholder generates a unique key.
This article refers to non-SXA dynamic placeholders. SXA placeholder keys follow a different convention.
The dynamic placeholder key looks like this:
{placeholder key}-{rendering unique suffix}-{unique suffix within rendering}
Where
rendering unique suffix -UID of a rendering that contains the placeholder. It guarantees a uniqueness to placeholder keys across different renderings.unique suffix within rendering- index number of a dynamically generated placeholder. The first number equals theSeed.
Assume that the dynamic placeholder content is used within the rendering with UID {7a943e27-b649-400c-986d-33d07f0f50ca}, count``2, and seed is 5. Sitecore generates these placeholder keys :
content-{7a943e27-b649-400c-986d-33d07f0f50ca}-5content-{7a943e27-b649-400c-986d-33d07f0f50ca}-6
This is an example of using DynamicPlaceholderDefinition:
This code generates five dynamic placeholders with ListItem as the key. A user can add a total of 10 placeholders through the rendering parameters. Each placeholder will be wrapped with <li> </li> tags.
You can improve the user experience with proper OutputModifier and use lambdas like this:
This code gives the following HTML for the second dynamically rendered placeholder:
Customizing dynamic placeholders from rendering parameters
You can customize dynamic placeholders with additional rendering parameters. This allows you to specify the amount of placeholders that Sitecore generates dynamically. Parameters can be read from the DynamicPlaceholderRenderContext.Parameters dictionary that you pass, for example, to the OutputModifier.
For example, this means that you can override the Count parameter from the DynamicPlaceholderDefinition,so that you can update the Count parameter from the Content Editor or the Experience Editor without changing the code.
The parameter name formats are these:
-
ph_placeholderKey_paramNameExample:
Name:
ph_column_count; value: 5. "column" dynamic placeholder will produce 5 placeholders.Name:
ph_column_width; value: 30px -
ph_placeholderKey_indexNumber_paramNameExample:
Name:
ph_column_2_width; value: 50px. The "width" parameter is passed only while the placeholder with index 2 is processed by the output modifier.
Customizing key generation
You can customize the way Sitecore generates dynamic placeholder keys with the mvc.getDynamicPlaceholderKeys pipeline. This pipeline has three default processors:
-
GetRenderingUniqueSuffixThe objective of this processor is to allow a placeholder key to be unique across a page. Returns the UID of a rendering that contains the generated placeholder.
-
GetUniqueKeysWithinRenderingThe objective of this processor is to allow a placeholder key to be unique within a concrete rendering. Returns the index number of a dynamic placeholder within the parent rendering. It generates this value each time during the rendering process. The first value is taken from the
Seedand then it increments it. -
AggregatePlaceholderKeysThis processor returns the aggregates placeholder key, rendering unique suffix and unique suffix within rendering in the this format:
{placeholder key}-{rendering unique suffix}-{unique suffix within rendering}. For example:GridCell-{7a943e27-b649-400c-986d-33d07f0f50ca}-0).
If you change the mvc.getDynamicPlaceholderKeys pipeline you must also update the mvc.getDynamicPlaceholderInitialKey pipeline. This pipeline is responsible for getting the initial placeholder key by the given dynamic placeholder key. The current implementation is based on RegExp -{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}}-[0-9]+$ and it tries to cut off the unique placeholder key suffix.
Known limitations
Dynamic placeholders have several limitations you must be aware of:
-
By default, placeholder settings work only with the initial dynamic placeholder key.
For example, the dynamic placeholder
@Html.Sitecore().DynamicPlaceholder("column", 2)becomes:@Html.Sitecore().Placeholder("column-{…}-0")@Html.Sitecore().Placeholder("column-{…}-1").The user can define a placeholder setting only for the column placeholder, and that be applicable both for
content-{…}-0andcontent-{…}-1. Defining the placeholder setting for a specific unique placeholder key (such ascolumn-{…}-1) will have no effect, unless theSitecore.Mvc.Pipelines.Response.GetDynamicPlaceholderInitialKey.RemovePlaceholderUniqueKeySuffixprocessor is enabled.Once
modeis set tooff:<mvc.getDynamicPlaceholderInitialKey><processor mode="off" type="Sitecore.Mvc.Pipelines.Response.GetDynamicPlaceholderInitialKey.RemovePlaceholderUniqueKeySuffix, Sitecore.Mvc"/></mvc.getDynamicPlaceholderInitialKey>it is possible to define placeholder settings for specific unique placeholder key, but now not for the initial key of a dynamic placeholder. -
Each independent call of
@Html.Sitecore().DynamicPlaceholder(…)knows nothing about each other. That's why if you insert two dynamic placeholders with the same name into the same rendering, you will get a collision. Example:@Html.Sitecore().DynamicPlaceholder("column", count: 2)…@Html.Sitecore().DynamicPlaceholder("column")becomes:
Html.Sitecore().Placeholder("column-{…}-0")Html.Sitecore().Placeholder("column-{…}-1")…Html.Sitecore().Placeholder("column-{…}-0")To get rid of collision in this situation, it's necessary to set the
Seed:@Html.Sitecore().DynamicPlaceholder("column", count: 2)…@Html.Sitecore().DynamicPlaceholder("column", seed: 10)becomes:
Html.Sitecore().Placeholder("column-{…}-0")Html.Sitecore().Placeholder("column-{…}-1")…Html.Sitecore().Placeholder("column-{…}-10") -
Note that you can override the
Countparameter through the rendering parameters at any time, so you must make sure that the seed is set with room for the count increase or set theMaxCount.