Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a Sitecore ribbon button with dropdown menu?

The Sitecore PageEditor and Preview interfaces feature a language selector button that triggers a "dropdown"/overlay menu where the user can select a language. How do I replicate this behavior?

(I set out to answer this question, and came up with a solution. Posting to SOF for comment/enhancement.)

like image 455
nickwesselman Avatar asked Jun 01 '12 17:06

nickwesselman


1 Answers

You can see how Sitecore does it in the Sitecore.Client assembly, Sitecore.Shell.Applications.WebEdit.Commands.ChangeLanguage and Sitecore.Shell.Applications.WebEdit.Commands.SetLanguage.

You'll need to create two commands of your own for this. One command is associated with the button, one is executed when a subitem is selected. The example is based on a scenario of changing a country cookie.

ChangeCountry Command

First, the command to display the menu. You can see that it displays a Menu with dynamic options. Overriding GetHeader and GetIcon allows the button itself to be dynamic based on the user's current selection.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sitecore.Shell.Applications.WebEdit.Commands;
using Sitecore.Diagnostics;
using Sitecore.Data.Items;
using Sitecore.Web.UI.Sheer;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.StringExtensions;
using System.Web;

namespace Prototype.Commands
{
    public class ChangeCountry : WebEditCommand
    {
        protected Dictionary<string, CountryOption> _countries = new Dictionary<string, CountryOption>
        {
            {"US", new CountryOption {
                ID = "US",
                Name = "United States",
                Icon = "Flags/32x32/flag_usa.png"
            }},
            {"CA", new CountryOption {
                ID = "CA",
                Name = "Canada",
                Icon = "Flags/32x32/flag_canada.png"
            }},
            {"MX", new CountryOption {
                ID = "MX",
                Name = "Mexico",
                Icon = "Flags/32x32/flag_mexico.png"
            }},
            {"DE", new CountryOption {
                ID = "DE",
                Name = "Germany",
                Icon = "Flags/32x32/flag_germany.png"
            }}
        };

        public override void Execute(Sitecore.Shell.Framework.Commands.CommandContext context)
        {
            Assert.ArgumentNotNull(context, "context");
            if (context.Items.Length == 1)
            {
                Item item = context.Items[0];
                SheerResponse.DisableOutput();
                Menu control = new Menu();
                //replace with lookup and loop of available values
                foreach (var key in _countries.Keys)
                {
                    var country = _countries[key];
                    string id = country.ID;
                    string header = country.Name;
                    string icon = country.Icon;
                    string click = "prototype:setcountry(country={0})".FormatWith(key);
                    control.Add(id, header, icon, string.Empty, click, false, string.Empty, MenuItemType.Normal);
                }
                SheerResponse.EnableOutput();
                SheerResponse.ShowPopup("ChangeCountryButton", "below", control);
            }
        }

        public override string GetHeader(Sitecore.Shell.Framework.Commands.CommandContext context, string header)
        {
            HttpCookie country = HttpContext.Current.Request.Cookies["country"];
            if (country != null && _countries.ContainsKey(country.Value))
            {
                return _countries[country.Value].Name;
            }
            return base.GetHeader(context, header);
        }

        public override string GetIcon(Sitecore.Shell.Framework.Commands.CommandContext context, string icon)
        {
            HttpCookie country = HttpContext.Current.Request.Cookies["country"];
            if (country != null && _countries.ContainsKey(country.Value))
            {
                return _countries[country.Value].Icon;
            }
            return base.GetIcon(context, icon);
        }

        protected class CountryOption
        {
            public string ID { get; set; }
            public string Name { get; set; }
            public string Icon { get; set; }
        }
    }
}

In either Commands.config or an include file, register the new command.

<command name="prototype:changecountry" type="Prototype.Commands.ChangeCountry,Prototype" />

Change Country Button

Create a new Chunk and Button under /sitecore/content/Applications/WebEdit/Ribbons/WebEdit/Experience. This ribbon strip is referenced/replicated in Preview mode as well. The button will use the following properties:

Ribbon Button

The Click field must match the name of your command, and the ID field must match the element ID provided in the SheerResponse.ShowPopup call above.

SetCountry Command

Next is the command that will be called when an item in your menu/dropdown is selected.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sitecore.Shell.Applications.WebEdit.Commands;
using System.Net;
using Sitecore.Diagnostics;
using Sitecore.Web.UI.Sheer;
using System.Web;

namespace Prototype.Commands
{
    public class SetCountry : WebEditCommand
    {
        public override void Execute(Sitecore.Shell.Framework.Commands.CommandContext context)
        {
            Assert.ArgumentNotNull(context, "context");
            var country = context.Parameters["country"];
            Assert.IsNotNullOrEmpty(country, "Country not found");
            HttpCookie cookie = new HttpCookie("country", country);
            HttpContext.Current.Response.Cookies.Add(cookie);
            WebEditCommand.Reload(WebEditCommand.GetUrl());
        }
    }
}

In our example, we're setting a cookie based on the selected value and reloading the page. The value passed in is based on the click event associated with the menu item in ChangeCountry. Likewise, the name of the command when configured needs to match what was used in the ChangeCountry click event.

<command name="prototype:setcountry" type="Prototype.Commands.SetCountry,Prototype" />
like image 100
nickwesselman Avatar answered Nov 17 '22 07:11

nickwesselman