Follow Field Target – Click through to the Item referenced by a Sitecore Field
Fed up the roundabout way of navigating to the Item referenced in one of Sitecore’s Link and List Field Types in the Content Editor I’ve built a concise Sitecore Marketplace Module that lets you click through to the Item the field is targeting.
https://marketplace.sitecore.net/Modules/F/Follow_Field_Target
Until now, the most effective way was to select Raw Values mode from the View Tab in the Ribbon, copy the field value, unselect Raw Values mode, paste the Guid into the Search box and press return.
Instead, the module I have build displays a Follow link directly above the Field which will take you straight to the Item and it supports all the major link and list field types in Sitecore;
- Droplink
- Grouped Droplink
- Droplist
- Grouped Droplist
- Droptree
- Treelist
- Mulitlist
It even works well with Multilists, items selected in both columns
I have developed the module to be lightweight, only two code files, minimum impact and work natively within Sitecore so it can be added to all Sitecore instances to help with ease of use.
Droplink and Grouped Droplink
The module makes use of Sitecore’s Menu item template which is added beneath the Field Type definition Item in the Core database. This displays the Follow link above each field when added to an Item. On the click event a Custom Command is made passing the field’s Target value.
Droplink and Group Droplink store their Target value as the Item’s Id so it’s the matter of getting value and using Sitecore.Web.WebUtil.GetFormValue
to get the guid and directing the Content Editor to that Item by telling the Client to load that item;
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FollowDropLink : Command | |
{ | |
public override void Execute(CommandContext context) | |
{ | |
var targetId = WebUtil.GetFormValue(context.Parameters["fieldId"]); | |
Sitecore.Context.ClientPage.SendMessage(this, "item:load(id=" + targetId + ")"); | |
} | |
} |
Multilist and Treelist
Despite both Multilist and Treelist raw values are the Ids the WebUtil.GetFormValue
method does not return the guid so they require significant more effort to work with.
The most effective approach I found is to use the Form
being submitted by the click event in the HttpRequest
. With the FieldId
from the Command
event we can loop through the parameters of the Form to find the Field matching that FieldId.
Oncethe correct field has been found we need to consider which Item has been selected by looking for a parameter matching the FieldId and either Selected or Unselected for a Mulitlist field or Selected and AllSelected for a Treelist field. This denotes which column contains the selected item.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FollowTreelist : Command | |
{ | |
public override void Execute(CommandContext context) | |
{ | |
ID id = ID.Null; | |
bool isId = false; | |
var fieldId = context.Parameters["fieldId"]; | |
if (!string.IsNullOrEmpty(fieldId)) | |
{ | |
var form = System.Web.HttpContext.Current.Request.Form; | |
if (form != null) | |
{ | |
string rawValue = form[string.Format("{0}{1}", fieldId, Constants.Selected)]; | |
if (string.IsNullOrEmpty(rawValue)) | |
{ | |
rawValue = form[string.Format("{0}{1}", fieldId, Constants.AllSelected)]; | |
} | |
string targetId = rawValue.Substring(rawValue.LastIndexOf("|", StringComparison.InvariantCultureIgnoreCase) + 1); | |
isId = ID.TryParse(targetId, out id); | |
// BUG fix – ID.TryParse fails unformatted ID string passed by FIELDID_all_selected | |
if (!isId) | |
{ | |
try | |
{ | |
id = new ID(targetId); | |
isId = true; | |
} | |
catch (Exception e) | |
{ | |
isId = false; | |
} | |
} | |
} | |
} | |
Sitecore.Context.ClientPage.SendMessage(this, "item:load(id=" + (isId ? id.ToString() : string.Empty) + ")"); | |
} | |
} |
Droplist and Grouped Droplist
As you would expect Droplist and Group Droplist are the hardest to build the Follow functionality for as they both have the Display Name of the Item as the selected value, not the Id. The display name really isn’t enough to go out and search the complete content tree to find the Item and redirect the user to it. There is only one possible one way we can definitely find the right Item – Field’s Source, so lets go get it.
Again, using the Form
submitted in the click event of the HttpRequest
I can loop through and select all fields on the Item that are a Droplist (or a Grouped Droplist). Once we have matching field types we need to consider that more than one Droplist (or Grouped Droplist) is present on the Item so we get a narrower list by selecting only fields whose Sources that contain an Item with that Display Name.
For our narrower list of Droplists (or Grouped Droplists) we need to parse each field’s Source. Again more scenario handling is needed as the Source could be an Item Id, Path or query. But fear note, the code handles it all!
With the source parsed we finally have a list of Strongly Typed Items, not just a display name! Now the easy part, loop through each field’s list of items to find the one matching the name and direct the user to their beloved Item!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class FollowGroupedDroplist : Command | |
{ | |
public override void Execute(CommandContext context) | |
{ | |
ID id = ID.Null; | |
Item item = context.Items[0]; | |
var targetName = WebUtil.GetFormValue(context.Parameters["fieldId"]); | |
if (item != null && !string.IsNullOrEmpty(targetName)) | |
{ | |
foreach (Field field in item.Fields.Where(Utility.IsGroupedDroplistField)) | |
{ | |
if (field.HasValue && field.Value.Equals(targetName) && !string.IsNullOrEmpty(field.Source)) | |
{ | |
var grandChildren = new List<Item>(); | |
Item sourceItem = item.Database.GetItem(field.Source); | |
if (sourceItem != null) | |
{ | |
grandChildren = (from c in sourceItem.Children | |
select c.GetChildren()).SelectMany(g => g).ToList(); | |
} | |
else | |
{ | |
List<Item> children = Utility.GetItemsFromQuery(field.Source, item).ToList(); | |
grandChildren = (from c in children | |
select c.GetChildren()).SelectMany(g => g).ToList(); | |
} | |
Item targetItem = grandChildren.FirstOrDefault(c => c.Name == targetName); | |
if (targetItem != null) | |
{ | |
id = targetItem.ID; | |
break; | |
} | |
} | |
} | |
} | |
Sitecore.Context.ClientPage.SendMessage(this, "item:load(id=" + (id != ID.Null ? id.ToString() : string.Empty) + ")"); | |
} | |
} |
And that’s it!
A nice little idea of useful functionality that at first glance is a really simple implementation but under the hood does have some magic to it. I’ll be adding this module to all my Sitecore instances, hope you enjoy!
Full source code is available on GitHub;
Pingback: Sitecore – Go to Item (Droplink) – Walid Rohiman
Hi Jonathan,
is it hard work for you to extend the module to work with internal links?
Best regards
Dirk
LikeLike
Hi Dirk,
It should be possible to work with internal links. Do you want to give me some more info around it and I can get back to you
Many thanks,
Jonathan
LikeLike
Hi Jonathan,
thanks a lot for your fast reply. Currently your module is working with the following field types: DropLink, DropTree, DropList, GroupedDropLink, GroupedDropList, Multilist and TreeList.
A customer of us uses excessively links from the Alias Template (Field Type ID: {4CEA552F-CEB7-452B-9516-9853185EDFD8}), Internal links (Field Type ID: {1B8A74B6-06E7-4BC3-97F3-DB7B11BFBE0B}) or Internal Links from a General Link.
It would be really nice if it is possible to follow the DataSource of these fields, too.
The question is how difficult is it for you to extend your module to achieve this and we always ask the developer before we implement custom solutions 🙂
Best regards
Dirk
LikeLike
Hey Dirk,
I’ll take a look this weekend for you and let you know how I get on 🙂
I believe for the General Link field there is already a Follow button present. I can’t remember if it works for internal links so I’ll double check that and see what options are available
Many thanks,
Jonathan
LikeLike
Hi Jonathan,
many thanks to you! If I can help on anything let me know. 😉
Best regards
Dirk
LikeLike
Hi Jonathan,
do you have any new knowledge?
Best regards
Dirk
LikeLike