This post is on the older side and its content may be out of date.
Be sure to visit our blogs homepage for our latest news, updates and information.
In this blog post I will show you how you can resolve the taxa selected in items, in their backend grid. We usually use at least one taxonomy to organize content and selected multiples items, for instance several tags. However, if we would like to show the taxa we have selected for each item in the items grid, we will see that the actual value will be the selected taxa ids. This does not suit our needs, since the ids of the items are not useful for any content editor. I will show you how you can get those ids, make a call to a web service and then display the taxa titles. The blog post requires general developer knowledge, as it concerns JavaScript, WebServices and knowegledge of the Sitefinity server-side API.
We will add a column to the grid, in which we will then populate the taxa titles for each row. The column insert is done through the Advanced settings. Go to ContentView -> Controls-> Select the module you want to customize -> Views -> BackendList -> View modes -> Grid -> Columns. Create a new column of type DataColumn. Bound it to taxonomy field name. We will get the ids directly from the items in the grid, though, it is good to bind to the according property. Enter the client template, this field is important since using it we will know where to insert the titles later. You can use the following template: <span id="tags">{{Tags}}</span> for tags. The column settings will look like this:
In order to plugin our logic in the grid binding, we will need to use an extension script. We can register one from the Advanced settings -> ContentView -> Controls-> Select the module you want to customize -> Views -> BackendList -> Scripts. Add new script, using your script location and passing the method you want to hook, in our case: OnModuleMasterViewLoaded. Example:
Here the script is used as an Embedded resource.
We will handle the onDataBinding event and will gather all taxa ids corresponding to each item in the grid. This way we can make a single call to the service and obtain them. Then the gathered data is used on itemDataBound, to replace our column values with the titles resolved. Here is the documented JavaScript code:
var
masterGridView;
// called by the MasterGridView when it is loaded
function
OnModuleMasterViewLoaded(sender, args) {
// the sender here is MasterGridView
masterGridView = sender;
// initialize our extender
dynamicModuleListViewExtender.init(sender);
var
binder = sender.get_binder();
sender.get_itemsGrid()._binder._itemDataBoundHandler = customItemDataBound;
binder.add_onDataBinding(handlerOnDataBinding);
};
function
handlerOnDataBinding(sender, args) {
var
extender = dynamicModuleListViewExtender.get_extender();
// get items taxa Ids
extender.getItemsTagsIds(sender, args);
// get tags
extender.getItemsCitiesIds(sender, args);
// get cities (custom classification)
}
function
customItemDataBound(key, dataItem, itemIndex, itemElement) {
var
itemEventArgs =
this
._getItemEventArgs(key, dataItem, itemIndex, itemElement);
var
h =
this
.get_events().getHandler(
'onItemDataBound'
);
// get taxa models and populate columns data for each item (row)
var
tags = dynamicModuleListViewExtender.get_extender()._tags;
dynamicModuleListViewExtender.get_extender().setColumnData(
"tags"
, tags, itemIndex, itemElement);
var
cities = dynamicModuleListViewExtender.get_extender()._cities;
dynamicModuleListViewExtender.get_extender().setColumnData(
"cities"
, cities, itemIndex, itemElement);
// call base handlers
if
(h) h(
this
, itemEventArgs);
return
itemEventArgs;
}
// The extender object, which we will use to get the data
var
dynamicModuleListViewExtender = (
function
() {
this
._extender =
null
;
// initialize variables
var
extender =
function
(sender) {
this
._sender = sender,
this
._itemsTagsIds = [];
this
._tags = [];
this
._itemsCitiesIds = [];
this
._cities = [];
}
extender.prototype = {
// get the items tags Ids - called on DataBinding
getItemsTagsIds:
function
(sender, args) {
this
._itemsTagsIds = [];
// all grid items, which will be bound
var
dataItems = args.get_dataItem().Items;
if
(dataItems && dataItems.length > 0) {
for
(
var
i = 0; i < dataItems.length; i++) {
// get the tags Ids for each item from the property
var
tags = dataItems[i].Tags;
// populate the associative array
this
._itemsTagsIds.push(tags);
}
}
if
(
this
._itemsTagsIds) {
// get the taxa items using the service
this
._tags =
this
.getTaxaData(
this
._itemsTagsIds);
}
},
// get the items cities (custom classification) Ids - called on DataBinding
getItemsCitiesIds:
function
(sender, args) {
this
._itemsCitiesIds = [];
var
dataItems = args.get_dataItem().Items;
if
(dataItems && dataItems.length > 0) {
for
(
var
i = 0; i < dataItems.length; i++) {
var
cities = dataItems[i].cities;
this
._itemsCitiesIds.push(cities);
}
}
if
(
this
._itemsCitiesIds) {
this
._cities =
this
.getTaxaData(
this
._itemsCitiesIds);
}
},
getTaxaData:
function
(ids) {
var
_self =
this
;
// url to our service
var
taxaServiceUrl =
"/Sitefinity/Services/TaxaService.svc/"
;
// stringify the data to be sent
var
itemsData = JSON.stringify(ids);
var
items =
null
;
// post request to get the data
jQuery.ajax({
type:
"POST"
,
async:
false
,
url: taxaServiceUrl +
"GetTaxaByIds"
,
contentType:
"application/json; charset=utf-8"
,
dataType:
"json"
,
data: itemsData,
success:
function
(data) {
items = data;
},
error:
function
(data) {
console.log(data);
}
});
// return the taxa models
return
items;
},
// set the grid column content
// selectorName: the selector to be used to find the column element (the id of the element in the column's client template
// items: the taxa collection
// itemIndex: the index of the items in the grid
// itemElement: the item row element - the <tr> of the grid
setColumnData:
function
(selectorName, items, itemIndex, itemElement) {
var
result =
""
;
// check if there are any taxa for this item
if
(items[itemIndex]) {
for
(
var
i = 0; i < items[itemIndex].length; i++) {
// build the result string
result += items[itemIndex][i].Title +
"; "
;
}
}
// find the grid row and column and set its content
// example: tags column for first item in the grid -> #tags0
jQuery(itemElement).find(
"#"
+ selectorName + itemIndex).html(result);
}
};
return
{
get_extender:
function
() {
if
(
this
._extender) {
return
this
._extender;
}
else
{
alert(
"extender not initialized"
);
}
},
init:
function
(sender) {
this
._extender =
new
extender(sender);
return
this
._extender;
}
}
}());
The service we will use is a specially prepared to serve the passed data and return the same associative array of TaxonModel:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(IncludeExceptionDetailInFaults =
true
, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public
class
TaxaService
{
[OperationContract]
[WebInvoke(Method =
"POST"
, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public
virtual
SimpleTaxonModel[][] GetTaxaByIds(Guid[][] taxaIds)
{
TaxonomyManager manager = TaxonomyManager.GetManager();
// Get All Ids
List<Guid> allIds =
new
List<Guid>();
for
(
int
i = 0; i < taxaIds.Length; i++)
{
if
(taxaIds[i].Length > 0)
{
allIds.AddRange(taxaIds[i]);
}
}
// Make a call to the database to get all taxa
var allTags = manager.GetTaxa<Taxon>().Where(t => allIds.Contains(t.Id))
.Select(t =>
new
SimpleTaxonModel()
// Convert the taxon to the model
{
Id = t.Id,
Title = t.Title
}).ToArray();
// populate the result
SimpleTaxonModel[][] result =
new
SimpleTaxonModel[taxaIds.Length][];
for
(
int
i = 0; i < taxaIds.Length; i++)
{
if
(taxaIds[i].Length > 0)
{
// set the correct taxa for each item
result[i] = allTags.Where(c => taxaIds[i].Contains(c.Id)).ToArray();
}
}
return
result;
}
}
public
class
SimpleTaxonModel
{
public
Guid Id {
get
;
set
; }
public
string
Title {
get
;
set
; }
}
We register the service in the global application file:
SystemManager.RegisterWebService(
typeof
(SitefinityWebApp.ExtensionScripts.TaxaService),
"Sitefinity/Services/TaxaService.svc"
);
Result:
Here is a video of the end result:
You can download the files from GitHub.
Subscribe to get all the news, info and tutorials you need to build better business apps and sites