Once upon a time I came across a requirement to display the item field along with the item name in Sitecore multilist with search field.
Many times multilist with search field shows duplicate item names, because there are items which are slimier in display name but different in the field values. This post is about displaying the difference inside the control itself.
The multilist with search is a very useful and powerful field which runs on javascript and it uses the Sitecore search functionality.
This is how the multilist with search looks like in Sitecore 8.2 :
What I wanted was a customization to have a field appended to item name:
The solution is a custome control, has four parts
1. Overriding the BucketList class.
2. Fetching the field in the BucketList.js file.
3. Config Changes
4. Core Database changes
First I decoded the Kernel with refelector and ILSpy and found the BucketList class in Sitecore.Buckets.FieldTypes.
Override this class in your project assembly. Following is the code:
namespace Sitecore.Buckets.FieldTypes
{
public class CustomisedMWS : BucketList
{
string fieldToAppend = "";
public override string OutputString(Item item)
{//Overriding so that selected items can be seen as modified
fieldToAppend = getFieldToAppend();
string fieldValueToAppend = "";
if (fieldToAppend != "")
fieldValueToAppend = item.Fields[fieldToAppend].ToString();
Item parentBucketItemOrParent = item.GetParentBucketItemOrParent();
string arg = (parentBucketItemOrParent != null) ? (" - " + parentBucketItemOrParent.DisplayName) : string.Empty;
return string.Format("{0} ({1}{2})", item.DisplayName +"-"+ fieldValueToAppend, item.TemplateName, arg);
}
protected override string ScriptParameters
{// Overriding to supply the appended field parameter to javascript
get
{
fieldToAppend = getFieldToAppend();
return string.Format("'{0}'", string.Join("', '", new object[]
{
this.ID,
this.ClientID,
base.PageNumber,
"/sitecore/shell/Applications/Buckets/Services/Search.ashx",
base.Filter,
SearchHelper.GetDatabaseUrlParameter("&"),
base.TypeHereToSearch,
this.Of,
base.EnableSetNewStartLocation,
this.fieldToAppend
}));
}
}
private string getFieldToAppend()
{// This method finds the field inside the source string and returns
if (base.Source.LastIndexOf("_fieldToAppend=") > 0)
return base.Source.Substring(base.Source.LastIndexOf("_fieldToAppend=") + 15);
else
return "undefined";
}
}
}
Many times multilist with search field shows duplicate item names, because there are items which are slimier in display name but different in the field values. This post is about displaying the difference inside the control itself.
The multilist with search is a very useful and powerful field which runs on javascript and it uses the Sitecore search functionality.
This is how the multilist with search looks like in Sitecore 8.2 :
These three Notice items, you are viewing inside multilist are coming from a field source string which looks like this:
StartSearchLocation={AB19F622-7FB9-42EC-BC9F-A0E5824EBF1F}&Filter=+_path:ab19f6227fb942ecbc9fa0e5824ebf1f|_templatename:Notice
The source items are Notice items having a field "TitleOrName"
You can see how TitleOrName field is coming appended to the item's Display names.
And I wanted this to be appended dynamically through field source like this:
StartSearchLocation={AB19F622-7FB9-42EC-BC9F-A0E5824EBF1F}&Filter=+_path:ab19f6227fb942ecbc9fa0e5824ebf1f|_templatename:Notice|_fieldToAppend=TitleOrName
The _fieldToAppend parameter decides which field is to be appended to the item display name.The solution is a custome control, has four parts
1. Overriding the BucketList class.
2. Fetching the field in the BucketList.js file.
3. Config Changes
4. Core Database changes
First I decoded the Kernel with refelector and ILSpy and found the BucketList class in Sitecore.Buckets.FieldTypes.
Override this class in your project assembly. Following is the code:
namespace Sitecore.Buckets.FieldTypes
{
public class CustomisedMWS : BucketList
{
string fieldToAppend = "";
public override string OutputString(Item item)
{//Overriding so that selected items can be seen as modified
fieldToAppend = getFieldToAppend();
string fieldValueToAppend = "";
if (fieldToAppend != "")
fieldValueToAppend = item.Fields[fieldToAppend].ToString();
Item parentBucketItemOrParent = item.GetParentBucketItemOrParent();
string arg = (parentBucketItemOrParent != null) ? (" - " + parentBucketItemOrParent.DisplayName) : string.Empty;
return string.Format("{0} ({1}{2})", item.DisplayName +"-"+ fieldValueToAppend, item.TemplateName, arg);
}
protected override string ScriptParameters
{// Overriding to supply the appended field parameter to javascript
get
{
fieldToAppend = getFieldToAppend();
return string.Format("'{0}'", string.Join("', '", new object[]
{
this.ID,
this.ClientID,
base.PageNumber,
"/sitecore/shell/Applications/Buckets/Services/Search.ashx",
base.Filter,
SearchHelper.GetDatabaseUrlParameter("&"),
base.TypeHereToSearch,
this.Of,
base.EnableSetNewStartLocation,
this.fieldToAppend
}));
}
}
private string getFieldToAppend()
{// This method finds the field inside the source string and returns
if (base.Source.LastIndexOf("_fieldToAppend=") > 0)
return base.Source.Substring(base.Source.LastIndexOf("_fieldToAppend=") + 15);
else
return "undefined";
}
}
}
Next create a condition in BucketList.js file which identifies whether the call is coming from regular mulilist or the custom multilist.
In case of custom multilist the item fields are required to be fetched from inside the Javascript code. The Sitecore Web API is a great way to fetch the item data asynchronously, see here how I used the RESTfulAPI Item service:
for (i = 0; i < reducedItems.length; i++) {
item = reducedItems[i];
if ((fieldToAppend == undefined) || (fieldToAppend == "undefined"))
{
multilist.options[multilist.options.length] = new Option((item.DisplayName || item.Name) + ' (' + item.TemplateName + (item.Bucket && (' - ' + item.Bucket)) + ')', item.ItemId);
}
else
{
var fieldValueToAppend='Unpublished Value.'
var _itemName = '';
var _templateName = '';
var _itemId = '';
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://blackrock/sitecore/api/ssc/item/"+item.ItemId);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
var jsonobj = JSON.parse(this.responseText);
fieldValueToAppend = jsonobj[fieldToAppend];
_itemName= jsonobj["ItemName"];
_templateName = jsonobj["TemplateName"];
_itemId = jsonobj["ItemID"];
multilist.options[multilist.options.length] = new Option(_itemName + '-' + fieldValueToAppend + ' (' + _templateName + (item.Bucket && (' - ' + item.Bucket)) + ')', _itemId);
}
};
xhr.send(null);
}
}
item = reducedItems[i];
if ((fieldToAppend == undefined) || (fieldToAppend == "undefined"))
{
multilist.options[multilist.options.length] = new Option((item.DisplayName || item.Name) + ' (' + item.TemplateName + (item.Bucket && (' - ' + item.Bucket)) + ')', item.ItemId);
}
else
{
var fieldValueToAppend='Unpublished Value.'
var _itemName = '';
var _templateName = '';
var _itemId = '';
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://blackrock/sitecore/api/ssc/item/"+item.ItemId);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
var jsonobj = JSON.parse(this.responseText);
fieldValueToAppend = jsonobj[fieldToAppend];
_itemName= jsonobj["ItemName"];
_templateName = jsonobj["TemplateName"];
_itemId = jsonobj["ItemID"];
multilist.options[multilist.options.length] = new Option(_itemName + '-' + fieldValueToAppend + ' (' + _templateName + (item.Bucket && (' - ' + item.Bucket)) + ')', _itemId);
}
};
xhr.send(null);
}
}
I am not an expert in writing JavaScript so this code is easy to understand.
Last two are pretty minor changes, which are to be done when you are making any custom control. Add a config entry to Sitecore>ControlSources .
And add a field type in /sitecore/system/Field types/List Types in core database. Use this field type with your bucket and specify the _fieldToAppend parameter in the source. Result:
Feel free to use this custom control in your solution.!
No comments:
Post a Comment