Sitecore 9 introduced the dynamic placeholder feature. Please follow the official documentation for more information about when and how to use it.

The problem with the default dynamic placeholders

At first glance, the new dynamic placeholders look very straightforward. Basically, we provide an integer which is the amount of placeholders that should be rendered. Additionally, we can define the seed which indicates the starting value that is used for key generation (see example below). Also the markup customization possibilities are quite nice. However, when I used it in a project I ran into a problem that made me realize that the simple mechanism comes with a huge downside.

Update: jammykam pointed out that the previous example using an accordion component wasn't beneficial to showcase the problem. Therefore I changed the example to a tab component.

Let's examine what I mean by that in a simple example. We want to create an tabs component where the Sitecore item structure is as follows:

tabs

This component should give the author the possibility to place other components (e.g. text, image, table) onto each tab content area. This is a classic scenario where dynamic placeholders come into play. If we would use the default dynamic placeholders in this case we might use the following code:

This way, the resulting placeholder keys look something like this:

  • tab-{2845070A-AEBD-4B45-A59D-88269B081204}-0
  • tab-{2845070A-AEBD-4B45-A59D-88269B081204}-1
  • tab-{2845070A-AEBD-4B45-A59D-88269B081204}-2

Each placeholder receives a unique key which is used to map renderings to it. However, we do not know which placeholder corresponds to which tab item. Here is why this is problematic: Let's assume an author is not happy with the sequence of the tab items and puts "Events" before "News". What happens now is that all renderings which have been assigned to "News" are getting rendered in "Events" and vice versa. Honestly, I couldn't come up with an elegant solution for this problem. If you found one, then I would be glad if you could give me a hint!

The solution

The solution I came up with is quite simple but involves extending the default functionality of dynamic placeholders. Basically, we need to add a unique identifier to each placeholder. Therefore I created a new helper method which lets us do that. This method takes in the placeholder name and a Sitecore.Data.ID object as parameters. The example mentioned before looks like this with the extended version:

This way the resulting placeholder keys look like this:

  • tab-{2845070A-AEBD-4B45-A59D-88269B081204}-{EE1CC84B-EB2D-4250-A3DE-F4DF0DB82138}
  • tab-{2845070A-AEBD-4B45-A59D-88269B081204}-{C6B08567-16ED-428E-9014-DD516B294E5B}
  • tab-{2845070A-AEBD-4B45-A59D-88269B081204}-{9487CD58-8CBB-423F-81D8-3E8612490D40}

SitecoreHelper extension

As mentioned before, I added a new extension method for the SitecoreHelper type.

Dynamic Placeholder pipeline customization

If you already followed the link to the official documentation of dynamic placeholders then you might have seen that Sitecore 9 offers pipelines to extend the basic dynamic placeholders. The following configuration and corresponding pipeline processors enable the recognition of a unique identifier in the placeholder key. The processors are built to work side-by-side with the existing features as for Sitecore 9.0 Update-1. As you might have noticed, I needed to replace the RemovePlaceholderUniqueKeySuffix processor so this statement might not be true in the future. Unfortunately, I couldn't figure out a way to avoid replacing a processor.