Simple custom field with working link database

So you have created a great new custom field that links items to items, but it is not working with the link database? Well the fix is not that hard. One way of getting around the problem and getting the custom field to register the links in the link database is to inherit the class CustomField and overriding the ValidateLinks, UpdateLink, Relink and RemoveLink methods.

Creating the custom field class

In order to demonstrate how this works I will be creating a very simple field that is a text string that holds itemIDs in a pipe separated string. So let us get onj with it. Create a class that inherits the abstract CustomField class.

public class SimpleField : CustomField
    {
        public SimpleField(Field innerField)
            : base(innerField)
        {
        }

        public SimpleField(Field innerField, string runtimeValue)
            : base(innerField, runtimeValue)
        {
        }
    }

Overriding the methods for the link database

Let us first create some supporting methods that we will need in the later implementation. The AddLink method adds an ItemID to the lsit of ItemIDs in the field, the ClearLink method removes an ItemID from the list of ItemIDs in the field and finally the ClearAllInvalidLinks method removes all ItemIDs that are invalid from the field.

        private void AddLink(ID id)
        {
            if (!Value.EndsWith("|") && Value.Length > 0)
            {
                Value += "|";
            }
            Value += id.ToString();
        }

        private void ClearLink(ID targetItemID)
        {
            Value = Value.Replace(targetItemID.ToString(), "");
            Value = Value.Replace("||", "|");
            Value = Value.TrimEnd('|');
            Value = Value.TrimStart('|');
        }

        private void ClearAllInvalidLinks()
        {
            foreach (var itemId in Value.Split('|'))
            {
                var targetItem = InnerField.Database.GetItem(new ID(itemId));
                if (targetItem != null)
                    ClearLink(targetItem.ID);
            }
        }

In order to get the custom field  to work with the link database we will need to override some methods. Let us start with the Relink method. This method is called when an item that is linked from the field is deleted and the user chooses to exchange the link in the field linking to the item for a new item.

public override void Relink(ItemLink itemLink, Item newLink)
        {
            Assert.ArgumentNotNull(itemLink, "itemLink");
            Assert.ArgumentNotNull(newLink, "newLink");
            Database database = Factory.GetDatabase(itemLink.TargetDatabaseName);
            if (database != null)
            {
                Item targetItem = database.GetItem(itemLink.TargetItemID);
                if (targetItem == null)
                {
                    ClearLink(itemLink.TargetItemID);
                }
                else
                {
                    if (Value.Contains(itemLink.TargetItemID.ToString()))
                    {
                        Value = Value.Replace(itemLink.TargetItemID.ToString(), newLink.ID.ToString());
                    }
                    else
                    {
                        AddLink(newLink.ID);
                    }
                }
            }
        }

Now the relinking works, but if the user chooses to remove the link in the dialog that appears when deleting a linked item we need to handle that. Override the RemoveLink method.

        public override void RemoveLink(ItemLink itemLink)
        {
            Assert.ArgumentNotNull(itemLink, "itemLink");
            ClearLink(itemLink.TargetItemID);
        }

We will also need to override the UpdateLink method to get it all to work, so let us go ahead.

        public override void UpdateLink(ItemLink itemLink)
        {
            Assert.ArgumentNotNull(itemLink, "itemLink");
            Database database = Factory.GetDatabase(itemLink.TargetDatabaseName);
            if (database == null)
            {
                ClearLink(itemLink.TargetItemID);
            }
            else
            {
                ClearAllInvalidLinks();
                Item targetItem = database.GetItem(itemLink.TargetItemID);
                if (targetItem != null)
                    AddLink(targetItem.ID);
            }
        }

Almost done with the code, but we will also need a function that validates links so the user gets the warning when deleting the linked items. The ValidateLinks method needs to be overridden.

public override void ValidateLinks(LinksValidationResult result)
        {
            Assert.ArgumentNotNull(result, "result");

            string itemIds = this.Value;
            if (string.IsNullOrEmpty(itemIds))
                return;

            foreach (var itemId in this.Value.Split('|'))
            {
                var targetItem = this.InnerField.Database.GetItem(new ID(itemId));
                if (targetItem != null)
                    result.AddValidLink(targetItem, targetItem.Paths.FullPath);
                else
                    result.AddBrokenLink(itemId);
            }
        }

Registering the custom field as a field type

So now the coding is done. Compile your project and open the FieldTypes.config. Add the following line to register your new SimpleField class as a new field type.

<fieldType name="SimpleField" type="MyNamespace.SimpleField,MyNamespace" />

All that is left to do is to add the SimpleField to the core database and you are good to go. Find the /sitecore/system/Field types/List Types – item in the core database and add a new Item derived from the /sitecore/templates/System/Templates/Template field type – template under it. Set the Assembly field to the name of your assembly (MyNamespace) and the Class field to the name of your class (MyNamespace.SimpleField).

All done. Go ahead and add your field to a template and verify that it works by adding some pipe separated ItemIDs to the new field. Of course this particular field is not very useful but it illustrates in a simple way how to handle the link database.

Leave a Reply

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