4

I'm implementing Dynamic Placeholders in Sitecore 7 as described in the articles

It is working correctly such that I can add the same Rendering to the layout and the renderings will go in the appropriate Dynamic Placeholder. However when I click to add a Rendering to the Dynamic Placeholder, the placeholder settings aren't being used.

What I am expecting is to be prompted with the allowed renderings that may be placed on the Dynamic Placeholder. Instead the Rendering/Layout tree is presented to manually select the rendering - giving Content Editors the ability to add disallowed renderings to the placeholder.

I have debugged the code and the correct Placeholder Settings Item is being found for the Dynamic Placeholder and the list of allowed Renderings are being retrieved however despite being set in the args the list is not presented for the User. See code below.

public class GetDynamicKeyAllowedRenderings : GetAllowedRenderings
{
    //string that ends in a GUID
    public const string DynamicKeyRegex = @"(.+){[\d\w]{8}\-([\d\w]{4}\-){3}[\d\w]{12}}";

    public new void Process(GetPlaceholderRenderingsArgs args)
    {
        Assert.IsNotNull(args, "args");

        // get the placeholder key
        string placeholderKey = args.PlaceholderKey;
        var regex = new Regex(DynamicKeyRegex);
        Match match = regex.Match(placeholderKey);

        // if the placeholder key text followed by a Guid
        if (match.Success && match.Groups.Count > 0)
        {
            // Is a dynamic placeholder
            placeholderKey = match.Groups[1].Value;
        }
        else
        {
            return;
        }

        Item placeholderItem = null;
        if (ID.IsNullOrEmpty(args.DeviceId))
        {
            placeholderItem = Client.Page.GetPlaceholderItem(placeholderKey, args.ContentDatabase,
                                                             args.LayoutDefinition);
        }
        else
        {
            using (new DeviceSwitcher(args.DeviceId, args.ContentDatabase))
            {
                placeholderItem = Client.Page.GetPlaceholderItem(placeholderKey, args.ContentDatabase,
                                                                 args.LayoutDefinition);
            }
        }

        // Retrieve the allowed renderings for the Placeholder
        List<Item> collection = null;
        if (placeholderItem != null)
        {
            bool allowedControlsSpecified;
            args.HasPlaceholderSettings = true;
            collection = this.GetRenderings(placeholderItem, out allowedControlsSpecified);
            if (allowedControlsSpecified)
            {
                args.CustomData["allowedControlsSpecified"] = true;
            }
        }
        if (collection != null)
        {
            if (args.PlaceholderRenderings == null)
            {
                args.PlaceholderRenderings = new List<Item>();
            }
            args.PlaceholderRenderings.AddRange(collection);
        }
    }
}

As this code was developed for Sitecore 6.5 / 6.6 I wonder if in the jump to Sitecore 7.0 brought a change that affects the latter half of the code

Jonathan Robbins
  • 2,027
  • 1
  • 16
  • 30

1 Answers1

6

I have found the source of the issue by decompiling the Sitecore 7 Kernel and viewing the default GetAllowedRenderings class. If Allowed Renderings are found the ShowTree Option needs to be set to false. See below

public class GetDynamicKeyAllowedRenderings : GetAllowedRenderings
    {
        //string that ends in a GUID
        public const string DynamicKeyRegex = @"(.+){[\d\w]{8}\-([\d\w]{4}\-){3}[\d\w]{12}}";

        public new void Process(GetPlaceholderRenderingsArgs args)
        {
            Assert.IsNotNull(args, "args");

            // get the placeholder key
            string placeholderKey = args.PlaceholderKey;
            var regex = new Regex(DynamicKeyRegex);
            Match match = regex.Match(placeholderKey);

            // if the placeholder key text followed by a Guid
            if (match.Success && match.Groups.Count > 0)
            {
                // Is a dynamic placeholder
                placeholderKey = match.Groups[1].Value;
            }
            else
            {
                return;
            }

            // Same as Sitecore.Pipelines.GetPlaceholderRenderings.GetAllowedRenderings from here but with fake placeholderKey
            // i.e. the placeholder without the Guid
            Item placeholderItem = null;
            if (ID.IsNullOrEmpty(args.DeviceId))
            {
                placeholderItem = Client.Page.GetPlaceholderItem(placeholderKey, args.ContentDatabase,
                                                                 args.LayoutDefinition);
            }
            else
            {
                using (new DeviceSwitcher(args.DeviceId, args.ContentDatabase))
                {
                    placeholderItem = Client.Page.GetPlaceholderItem(placeholderKey, args.ContentDatabase,
                                                                     args.LayoutDefinition);
                }
            }

            List<Item> collection = null;
            if (placeholderItem != null)
            {
                bool allowedControlsSpecified;
                args.HasPlaceholderSettings = true;
                collection = this.GetRenderings(placeholderItem, out allowedControlsSpecified);
                if (allowedControlsSpecified)
                {
                    // Hide the Layout/Rendering tree to show the Allowed Renderings
                    args.Options.ShowTree = false;
                }
            }
            if (collection != null)
            {
                if (args.PlaceholderRenderings == null)
                {
                    args.PlaceholderRenderings = new List<Item>();
                }
                args.PlaceholderRenderings.AddRange(collection);
            }
        }
    }

This is a change brought in by Sitecore 7 it seems.

Jonathan Robbins
  • 2,027
  • 1
  • 16
  • 30
  • Hey..nice work Jonathan. Is it possible to select the first allowed rendering and apply it to the placeholder without popping the "Select a Rendering" dialogue ?? – Prathamesh dhanawade Oct 14 '15 at 12:43
  • That's a good question. It should be possible but it might take a sizeable amount of work. Essentially where I set args.Options.ShowTree = false; you need to make a call for the allowed renderings. Then decompile the Sitecore code to find what the button click of Select a Rendering does and copy it after the allowed renderings call. – Jonathan Robbins Oct 14 '15 at 13:15
  • Exactly what i am looking for now....this means i will have to extend sitecore's implementation of applying a rendering. Any lead on where i can find that code.? – Prathamesh dhanawade Oct 14 '15 at 13:19
  • I had a quick routing around and the pipeline getPlaceholderRenderings gets the allowed renderings and that Select a Rendering seems to be based on the pipeline getRenderingDatasource, so have a loot at the code for the pipeline's processors and you should be able to make it work – Jonathan Robbins Oct 14 '15 at 13:38
  • I had a go with the code but could not find a generic solution for example if i want to use same thing for some other rendering. Is it possible in some other way similar to setting standard values to an Item template or so ? – Prathamesh dhanawade Oct 15 '15 at 06:35
  • Okay, I recommend posting a new questions with what you are trying to achieve. I'll try to get some time to instigate tonight – Jonathan Robbins Oct 15 '15 at 14:53
  • I have already posted one http://stackoverflow.com/questions/33031246/sitecore-8-automatically-fill-a-placeholder-by-a-default-rendering – Prathamesh dhanawade Oct 16 '15 at 05:16