Simplify layout details in page editor using dynamic datasource and more..

Posted 10/02/2013 by asura

Just when you think you have seen the worst of all Sitecore implementations, you get surprised with another one. This is one of those instances and the solution we came up with cleaned out a lot of unnecessarily complicated code and a ton of sublayouts on the item.

Disclaimer: I am not a big fan of crazy customizations on Page Editor, which end up causing issues.  

I prefer to use a handful of sublayouts to achieve one piece of functionality. For instance, if you had an Accordion where there are difference kind of panels, one specific to video, one specific for images and one for mixed content. I would envision one sublayout to handle the functionality of the Accordion and on the backend, we would have a few templates, one to define the Accordion panel settings, and the others to define each kind and the items that go along with it.

If all goes well, we will have a parent item (the page), the content folder under it with supporting items to populate the page. In this case it would have an item of Accordion Panel template and it could have one or more items to define the panels in the Accordion.

First, we need a base sublayout that can handle the dynamic datasource we specify using a sitecore query.

        
        public Item DataSource
        {
            get
            {
                if (_dataSource == null)
                    if (Parent is Sublayout)
                    {
                        string text = ((Sublayout)Parent).DataSource;
                        if (!string.IsNullOrEmpty(text))
                        {
                            if (text.StartsWith("query:"))
                            {
                                text = text.Remove(0, 6); //remove the query:
                                _dataSource = Sitecore.Context.Item.Axes.SelectSingleItem(text); //Execute the query
                            }
                            else
                                _dataSource = Sitecore.Context.Database.GetItem(((Sublayout)Parent).DataSource);
                        }
                    }

                return _dataSource;
            }
            set { _dataSource = value; }
        }

Next, define templates to store information for the main Accordion item and the different panels that can be rendered under it.

Now for the code in the Accordion sublayout. We write the generic code to render the UI using ListView. We are also going to add two edit frames, one for adding new Accordion panels and one for editing existing panels:


 

Click here to insert new Accordion item.

Add Accordion Item

Edit Accordion Item

Once that is completed, we add the Accordion sublayout to the Presentation or it could also be added as part of a Branch template or Standard Values in which case it would have a preset datasource of query:ancestor-or-self::*/Content/Main Content/Accordion

As you can see we are referring to two buttons, one called Accordion and the other called Accordion Item and these have been defined in the Core database at the path shown. These buttons are attached to the two commands defined in the custom config for the project.

 
      
      

In the Accordion sublayouts code behind, we set the parameters on the EditFrames with appropriate item id's.

 editAccordionLink.Parameters = "datasource=" + item.ID.ToString();

In the add command, we utilize the datasource to add the new accordion item to the right parent, in this case the main Accordion panel.

 
        [UsedImplicitly]
        protected void Run(ClientPipelineArgs args)
        {
            string itemUrl;
            string siteName;
            Assert.ArgumentNotNull(args, "args");
            string item = args.Parameters["itemid"];
            string datasource = args.Parameters["datasource"];
            Language language = Language.Parse(args.Parameters["language"]);
            Item itemNotNull = Client.GetItemNotNull(item, language);
            Item datasourceItem = null;
            if (SheerResponse.CheckModified())
            {
                if (!args.IsPostBack)
                {
                    if (itemNotNull.Access.CanCreate())
                    {
                        UrlString urlString = ResourceUri.Parse("control:Applications.WebEdit.Dialogs.AddMaster").ToUrlString();
                        itemNotNull.Uri.AddToUrlString(urlString);
                        SheerResponse.ShowModalDialog(urlString.ToString(), true);
                        args.WaitForPostBack();
                    }
                    else
                    {
                        SheerResponse.Alert("You do not have permission to create an item here.", new string[0]);
                        return;
                    }
                }
                else
                {
                    if (args.HasResult)
                    {
                        char[] chrArray = new char[1];
                        chrArray[0] = ',';
                        string[] strArrays = args.Result.Split(chrArray);
                        string str = strArrays[0];
                        string str1 = strArrays[1];
                        BranchItem branchItem = Client.ContentDatabase.Branches[str, itemNotNull.Language];
                        Assert.IsNotNull(branchItem, typeof(BranchItem));

                        if (!string.IsNullOrEmpty(datasource))
                            datasourceItem = Client.GetItemNotNull(datasource, language);

                        if (datasourceItem != null)
                            itemNotNull = datasourceItem;

                        this.ExecuteCommand(itemNotNull, branchItem, str1);
                        Client.Site.Notifications.Disabled = true;
                        Item item1 = Context.Workflow.AddItem(str1, branchItem, itemNotNull);
                        Client.Site.Notifications.Disabled = false;

And in the edit command, we use the datasource to open a content edit screen for the Accordion Item:

 
        public override void Execute(CommandContext context)
        {
            Assert.ArgumentNotNull(context, "context");
            if (!string.IsNullOrEmpty(context.Parameters["datasource"]))
            {
                UrlString urlString = new UrlString("/sitecore/shell/Applications/Content Manager/default.aspx");
                urlString["fo"] = context.Parameters["datasource"];
                urlString["mo"] = "preview";
                string features = EditItem.GetFeatures();
                object[] objArray = new object[5];
                objArray[0] = "window.open('";
                objArray[1] = urlString;
                objArray[2] = "', 'SitecoreWebEditEditor', '";
                objArray[3] = features;
                objArray[4] = "')";
                SheerResponse.Eval(string.Concat(objArray));
            }
        }

Using this method we were able to replace a lot of redundant code, templates and sublayouts. This also made it easier for the content editors to easily add and manage, one or more Accordions on a page.

Share:

Archive

Syndication