0

I've constructed a dynamic placeholder using the top answer in this post: https://stackoverflow.com/questions/15134720/sitecore-dynamic-placeholders-with-mvc.

This implementation uses the GUID of the current context item to generate a unique id to append to the end of each dynamic placeholder. Instead of using a GUID, I would like the placeholder keys to be sequential. For example, if there is one dynamic row placeholder on the page, the placeholder would become row1. If two row placeholder are on a page, they would be row1, and row2. Three would be row1, row2, and row3. And so on.

I have successfully implemented the code from the above post in my environment, but I've been unable to get the sequential count of dynamic placeholders to work. Originally, I tried a static variable on the placeholder class, but the value of that field persisted on page refresh (If I started with row1, row2 on refresh I would get row3, row4). Next I tried to read the number of row placeholders on the page from the current context item, however the list that is returned never contains the row placeholder, only its parent.

Here is the rendering which contains the dynamic placeholder call:

<div class="row_block">
    @Html.Sitecore().DynamicPlaceholder("row")
</div>

And here is my modified SitecoreHelper class from the original post:

public static class SitecoreHelper
{
    public static HtmlString DynamicPlaceholder(this Sitecore.Mvc.Helpers.SitecoreHelper helper, string dynamicKey)
    {
        int id = GetId(dynamicKey);
        return helper.Placeholder(string.Format("{0}{1}", dynamicKey, id++));
    }

    private static int GetId(string placeHolderName)
    {
        bool NeedIncrement = false;
        int IncrementStep = 0;
        var myPlaceholders = ContextService.Get().GetInstances<PlaceholderContext>();
        foreach (PlaceholderContext myPHContext in myPlaceholders)
        {
            if (myPHContext.PlaceholderName == placeHolderName || myPHContext.PlaceholderName.StartsWith(placeHolderName))
            {
                NeedIncrement = true;
                IncrementStep++;
            }
        }
        if (!NeedIncrement)
        {
            IncrementStep = 1;
        }
        return IncrementStep;
    }
}

Is there an way for me to generate sequential ids for these placeholder keys based on the number of times the base dynamic key appears? Thanks for the help!

1 Answer 1

3

I have previously created a similar implementation, though taking a slightly different approach, based on the renderings of the current item, rather than the available placeholder contexts.

private static int GetId(string placeHolderName)
{
    // Get all renderings from current item
    IEnumerable<RenderingReference> renderings = ContextItem.Visualization.GetRenderings(Context.Device, false);

    // Get all renderings of current type
    renderings = renderings.Where(x => x.RenderingID == RenderingContext.Current.Rendering.RenderingItem.ID);

    // Get all renderings in current placeholder
    renderings =
        renderings.Where(
            x => x.Placeholder.TrimStart('/') == RenderingContext.Current.Rendering.Placeholder.TrimStart('/'));

    // Find the index of the current rendering
    var index =
        renderings.ToList()
            .FindIndex(x => new Guid(x.UniqueId) == RenderingContext.Current.Rendering.UniqueId);
    return index + 1;
}

Note that the above is based on renderings containing dynamic placeholder keys, and thus assumes that each dynamic placeholderkey is unique per rendering, i.e. if you add multiple identical dynamic placeholders to different renderings, it will not get incremented.

Alternatives

Please be aware, that sequential dynamic placeholder keys (the above, as well as your own suggestion) pose some limitations. The order of the renderings, for example, is bound to the sequential order of the placeholders, and you will not be able to move or delete rows (the placeholder key will change once rows swap position). Also, you would need additional logic to handle placeholder settings.

You should consider using one of the available packages. I have completely dumped my own implementation and started using Fortis Dynamic Placeholders instead. That is well tested and well proven, and is (currently) being actively maintained. As long as your editors are based in the Experience Editor, they will not be confused with the GUID based placeholder keys.

1
  • Thanks, this worked perfectly! We're upgrading a Web Forms project that uses a sequential dynamic placeholder to MVC so we wanted to replicate that functionality during the upgrade process. We had noticed the limitations of the current implementation and it's on our to do list to transition the placeholder to a more robust solution later in the project.
    – c-bro
    Apr 3, 2017 at 14:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.