Sitecore

Extending General Link field in Sitecore

Sitecore provides a General link as an out-of-the-box field. This field enables Content Editors to insert links for one of the following options:


A. A link to the Sitecore item
B. Link to an external URL
C. A custom anchor tag
D. Email address
E. A JavaScript function
F. A Media link

Why this Blog?

In this blog post, I will be describing how to extend External Links provided by Sitecore. By default, when Insert external link (which is the 3rd option shown in the above image) is clicked, the popup below is displayed.

The Content author can provide a small description for the link, the actual URL where it needs to be re-directed, the Target Window (whether to open in the same browser or in a new browser), and other fields.

At times, customers want to capture some additional information like google analytics tags, etc. Let’s look at how to add this additional field

  1. Edit External link in Core DB

In the Core DB, go to the external link item by tracking the path /Sitecore/system/Field Types/Link Types/ General Link/Menu/External Link and perform the below changes:

  • The message field’s default value(contentlink:externallink(id=$Target) needs to be substituted with a custom value (contentlink:externallinkextend(id=$Target)).
  • Go to General Link (parent item of Menu), as shown in the above image, and update the Control field with the value content:ExtendLinks.

2. Write custom code to create a new message handler


A. Create custom control: Create a new class named ExternalLinkExtendForm, which will be inherited from the class ExternalLinkForm. The code for the same is presented in the shown image:

using Sitecore;
using Sitecore.DependencyInjection;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.Dialogs.ExternalLink;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.Web.UI.Sheer;
using Sitecore.Xml;
using System;
using System.Collections.Specialized;
using System.Xml;

namespace Foundation.Universal.Extensions
{
    public class ExternalLinkExtendForm: ExternalLinkForm
    {
        protected Edit FeatureName;
        protected Edit FeaturePosition;
        protected Edit FeatureOption;
        private ILinkExtendForm _linkExtendForm;
        public ExternalLinkExtendForm()
        {
            _linkExtendForm = (ILinkExtendForm)ServiceLocator.ServiceProvider.GetService(typeof(ILinkExtendForm));
            
        }

        private NameValueCollection customLinkAttributes;
        protected NameValueCollection CustomLinkAttributes
        {
            get
            {
                if (customLinkAttributes == null)
                {
                    customLinkAttributes = new NameValueCollection();
                    ParseLinkAttributes(GetLink());
                }

                return customLinkAttributes;
            }
        }

        protected override void ParseLink(string link)
        {
            base.ParseLink(link);
            ParseLinkAttributes(link);
        }

        protected virtual void ParseLinkAttributes(string link)
        {
            Assert.ArgumentNotNull(link, "link");
            XmlDocument xmlDocument = XmlUtil.LoadXml(link);
            if (xmlDocument == null)
            {
                return;
            }

            XmlNode node = xmlDocument.SelectSingleNode("/link");
            if (node == null)
            {
                return;
            }

            CustomLinkAttributes["FeatureNameAttributeName"] = XmlUtil.GetAttribute("FeatureNameAttributeName", node);
        }

        protected override void OnLoad(EventArgs e)
        {
            Assert.ArgumentNotNull(e, "e");
            base.OnLoad(e);
            if (Context.ClientPage.IsEvent)
            {
                return;
            }

            _linkExtendForm.LoadControls(CustomLinkAttributes,ref FeatureName);
        }

        protected override void OnOK(object sender, EventArgs args)
        {
            Assert.ArgumentNotNull(sender, "sender");
            Assert.ArgumentNotNull(args, "args");
            string path = GetPath();
            string attributeFromValue = GetLinkTargetAttributeFromValue(Target.Value, CustomTarget.Value);
            Packet packet = new Packet("link", new string[0]);
            SetAttribute(packet, "text",Text);
            SetAttribute(packet, "linktype", "external");
            SetAttribute(packet, "url", path);
            SetAttribute(packet, "anchor", string.Empty);
            SetAttribute(packet, "title", Title);
            SetAttribute(packet, "class", Class);
            SetAttribute(packet, "target", attributeFromValue);

            SetAttribute(packet, "FeatureNameAttributeName", FeatureName);
          
            SheerResponse.SetDialogValue(packet.OuterXml);
            SheerResponse.CloseWindow();
        }
        private string GetPath()
        {
            string url = this.Url.Value;
            if (url.Length > 0 && url.IndexOf("://", StringComparison.InvariantCulture) < 0 && !url.StartsWith("/", StringComparison.InvariantCulture))
            {
                url = string.Concat("http://", url);
            }

            return url;
        }
    }
}

B. Create a new message handler: This handler will be called when an external link is clicked from the General link field.


Create a new class named ExtendLinks (should be exactly as what is described in the control field of General Link (As per step 1. a). Add the code below in this recently created class:

using Sitecore;
using Sitecore.Diagnostics;
using Sitecore.Shell.Applications.ContentEditor;
using Sitecore.Text;
using Sitecore.Web.UI.Sheer;

namespace Foundation.Universal.Extensions
{
    public class ExtendLinks : Link
    {
        public override void HandleMessage(Message message)
        {
            Assert.ArgumentNotNull((object)message, nameof(message));
            base.HandleMessage(message);
            if (message["id"] != this.ID)
                return;
            string name = message.Name;

            switch (name)
            {
                case "contentlink:externallinkextend":
                    {
                        string uri = UIUtil.GetUri("control:ExternalLinkExtendForm");
                        UrlString urlString = new UrlString(uri);
                        string strUrlString = urlString.ToString();
                        this.Insert(strUrlString);
                        break;
                    }
            }
        }
    }
}

3. Register control source

Register the control with Sitecore and to display the new custom field on the external link dialog –

  • Create an include config file and put down the specified code
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <controlSources>
		<source assembly="Foundation.Universal" namespace="Foundation.Universal.Extensions" mode="on" prefix="content"/>
    </controlSources>
  </sitecore>
</configuration>

  • Go to the path “sitecore\shell\Applications\Dialogs”  in file explorer and create a duplicate folder named ExternalLinkExtend from the folder ExternalLink
  • Open the folder ExternalLinkExtend and rename the file ExternalLink.xml to ExternalLinkExtend.xml
  • Add the FeatureName attribute in the newly created file(ExternalLinkExtend.xml), just below the Alternate Text field. The exact is depicted below:

4. Publish the code and Verify

Once all the above changes are accomplished, at a final stage we need to deploy all our changes (custom code) and have to confirm whether the newly created custom field is observable or not. After deploying, go to any General Link field and click on the external link option. The new custom field, Analytics Feature Name, is visible.

Once the text box is available, enter any value and check the raw value to see if everything works as expected

Stay tuned for more in the coming days….

Did you find this useful? If so, please share with your connections.

Leave a Reply

Your email address will not be published. Required fields are marked *