How to customize a general link button to create a dynamic link with an internal link and a data source in Sitecore

I needed to generate a dynamic link with an internal link and data source item. For example, I wanted to create a link like the one below.

https://local.com/faq#heading-4f8d1f56-54af-4f2b-9f9b-0dcc6bcdec0b

/faq- Sitecore page item

4f8d1f56-54af-4f2b-9f9b-0dcc6bcdec0b - data source item

Let's dive deeper into the process.

  1. Switch to the core database in the CMS.
  2. Navigate to the folder path:
     /sitecore/system/Field types/Link Types/General Link/Menu
  3. Create a new item for the custom link button and provide a display name for the message.
    **Message:** This is similar to the command action name. 
     Use: `contentlink:accordionlink(id=$Target)`



  4.  Expand the Link Field to include the custom button action. Use `"control:AccordionLink"` to find the AccordionLink control and open the dialog box.



  5. Create an XML file for a custom link to open a dialog box with an internal link and data source item.



  6. Extend a LinkForm field to develop a new custom submit action for a link button.

  7. - The `OnLoad` method provides the initial data to the dialog box, while the `OnOK` method handles the actual action that submits the form.


  8. Go to any General Link field, and you’ll find the new link button has been added.



  9. Now, click the link, and there you go! 


Please find the XML file code.
<?xml version="1.0" encoding="utf-8" ?>
<control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense">
	<AccordionLink>
		<FormDialog Icon="Network/32x32/link.png" Header="Insert a link" Text="Select both page link and datasource item. When done click the Link button." OKButton="Link">
			<CodeBeside Type="Unity.Project.Unity.sitecore.shell.Applications.Dialogs.InsertLinkForm, Unity.Project.Unity"/>
			<DataContext ID="InternalLinkDataContext"/>
			<DataContext ID="DataSourceContext" Root="{E686F6D8-5EC7-4E3D-A3EC-E6789A874F34}"/>

			<GridPanel Class="scFormTable" CellPadding="2" Columns="2" Width="100%">
				<Label For="Text" GridPanel.NoWrap="true">
					<Literal Text="Link Text:"/>
				</Label>
				<Edit ID="Text" Width="100%" GridPanel.Width="100%"/>
			</GridPanel>
			<div class="scStretch">
				<div class="col2">
					<Label For="InternalLinkTreeview" GridPanel.NoWrap="true">
						<Literal Text="Page Link:"/>
					</Label>
					<Scrollbox Border="1px solid #CFCFCF">
						<TreeviewEx ID="InternalLinkTreeview" DataContext="InternalLinkDataContext" Root="true" Style="padding-top: 10px" ContextMenu='Treeview.GetContextMenu("contextmenu")' />
					</Scrollbox>
				</div>
				<div class="col2">
					<Label For="DataSourceview" GridPanel.NoWrap="true">
						<Literal Text="Datasource Item:"/>
					</Label>
					<Scrollbox Border="1px solid #CFCFCF">
						<TreeviewEx ID="DataSourceview" DataContext="DataSourceContext"  Style="padding-top: 10px" ContextMenu='Treeview.GetContextMenu("contextmenu")' />
					</Scrollbox>
				</div>
			</div>
		</FormDialog>
	</AccordionLink>
</control>
Please find the CS file code.
 public class InsertLinkForm : LinkForm
{
    protected DataContext InternalLinkDataContext;
    protected TreeviewEx InternalLinkTreeview;
    protected DataContext DataSourceContext;
    protected TreeviewEx DataSourceview;
    protected Edit Text;
    protected override void OnLoad(EventArgs e)
    {
        Assert.ArgumentNotNull((object)e, nameof(e));
        base.OnLoad(e);
        if (Context.ClientPage.IsEvent)
            return;
        this.InternalLinkDataContext.GetFromQueryString();
        this.DataSourceContext.GetFromQueryString();
        string queryString = WebUtil.GetQueryString("ro");
        string linkAttribute1 = this.LinkAttributes["url"];
        //string linkAttribute2 = this.LinkAttributes["target"];
        this.Text.Value = this.LinkAttributes["text"];
        //string Anchor = this.LinkAttributes["anchor"];
        string linkAttribute3 = this.LinkAttributes["id"];
        if (string.IsNullOrEmpty(linkAttribute3) || !ID.IsID(linkAttribute3))
        {
            this.SetFolderFromUrl(linkAttribute1);
        }
        else
        {
            ID id = new ID(linkAttribute3);
            if (Sitecore.Client.ContentDatabase.GetItem(id, this.InternalLinkDataContext.Language) == null && !string.IsNullOrWhiteSpace(linkAttribute1))
                this.SetFolderFromUrl(linkAttribute1);
            else
                this.InternalLinkDataContext.SetFolder(new ItemUri(id, this.InternalLinkDataContext.Language, Sitecore.Client.ContentDatabase));
        }
        if (queryString.Length <= 0)
            return;
        this.InternalLinkDataContext.Root = queryString;
    }

    /// Handles a click on the OK button.
    /// 
    /// 
    /// When the user clicks OK, the dialog is closed by calling
    /// the CloseWindow method.
    protected override void OnOK(object sender, EventArgs args)
    {
        Assert.ArgumentNotNull(sender, nameof(sender));
        Assert.ArgumentNotNull((object)args, nameof(args));
        Item selectionItem = this.InternalLinkTreeview.GetSelectionItem();
        Item DataSourceItem = this.DataSourceview.GetSelectionItem();
        if (selectionItem == null || DataSourceItem == null)
        {
            Context.ClientPage.ClientResponse.Alert("Select page and datasource item.");
        }
        else
        {
            string str = "heading-" + DataSourceItem.ID.Guid.ToString("D").ToLower();
            Packet packet = new Packet("link", Array.Empty());
            LinkForm.SetAttribute(packet, "text", (Control)this.Text);
            LinkForm.SetAttribute(packet, "linktype", "internal");
            LinkForm.SetAttribute(packet, "anchor", str);
            LinkForm.SetAttribute(packet, "id", selectionItem.ID.ToString());
            Assert.IsTrue(!string.IsNullOrEmpty(selectionItem.ID.ToString()) && ID.IsID(selectionItem.ID.ToString()), "ID doesn't exist.");
            Context.ClientPage.ClientResponse.SetDialogValue(packet.OuterXml);
            base.OnOK(sender, args);
        }
    }
    private void SetFolderFromUrl(string url)
    {
        Assert.ArgumentNotNull((object)url, nameof(url));
        if (this.LinkType != "internal")
            url = "/sitecore/content" + Settings.DefaultItem;
        if (url.Length == 0)
            url = "/sitecore/content";
        if (!url.StartsWith("/sitecore", StringComparison.InvariantCulture))
            url = "/sitecore/content" + url;
        this.InternalLinkDataContext.Folder = url;
    }
}

Comments

Popular posts from this blog

How to Enable Voice Search in Sitecore Content Editor

How to Create a Component in Next.js for XM Cloud

How to Create a Custom Component in XM Cloud.