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 datavar 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