Many of you have used our Taxonomy Fields for displaying the taxa an item's marked with on the frontend. We've received some feedback form clients that in certain cases you'd prefer to have this list of taxa behave as clickable taxonomy links, which when clicked can dynamically filter the ListView control.
As you know, by default the Hierarchical/FlatTaxonField when in Read mode will output the list of taxa names, as a clear text. For today's blog post we'll see how we can customize the way the taxa are displayed, and achieve filtering functionality.
We are going to adopt the good old approach of using an external widget template. This approach has many benefits. First, it allows us to easily add a code-behind to any template, and implement the additional business logic. Second, since all ContentView-based widgets use a databound control, like RadListView for displaying the list of items on the frontend, we could easily subscribe to the ItemDataBound event of the list view, and get access to each item that gets bound, and to its properties.
For the current blog post, let's take the News widget for example. We can copy its default template for TitlesDatesSummariesListView and paste the HTML in a new UserControl.
Then, while still on the presentational part, we can define a placeholder to display our category links. For example a label:
Then we can move to our new UserControl's code-behind part, to implement our business logic.
First, we need to subscribe to the ItemDataBound event of our RadListView control:
Next we have to get the actual Sitefinity content item that is being passed as parameter to the
We also need to get a reference to our control that is going to display the desired categories links, and set its value:
Inside the
Please note the
Once we have the list of assigned categories what we need to do is load each category, as we currently have only its ID. We can then simply iterate through the list of category IDs, load each category and then using its own Name, the name of the Taxonomy it belongs to and the name of the single Taxon from that Taxonomy we can construct the filtering URL parameter in a similar fashion: -in-Category/Categories/yourCategoryName . This is the default format our Sitefinity TaxonomyEvaluator is looking for, and it will ensure us the correct filtering behavior. The finishing stop is to combine this with the absolute URL of the page we're currently on and we end up with something like:
With this our job on the custom template is complete - simply build the project and then proceed with specifying the path to the custom template in your widget's advanced settings TemplatePath property, so it will start using the custom template instead of the default one.
For your convenience you can find the complete sample of the custom template attached to this blog post:
CustomTemplates - displaying the categories as clickable links
As an end result you should have the categories you've assigned each item to, displayed as click-able links under each item in the ListView.
A short video demonstrating this functionality can be found here.
As a bottom line I just wanted to point out that although the sample demonstrates achieving this functionality with a News widget, you should be aware of the fact that the approach is pretty much universal, so it can be very easily adapted to any other ContentView based widget if you follow the described steps.
I hope you enjoyed this post, please keep in touch for more useful tips and tricks that can help you customize the product behavior.
As you know, by default the Hierarchical/FlatTaxonField when in Read mode will output the list of taxa names, as a clear text. For today's blog post we'll see how we can customize the way the taxa are displayed, and achieve filtering functionality.
We are going to adopt the good old approach of using an external widget template. This approach has many benefits. First, it allows us to easily add a code-behind to any template, and implement the additional business logic. Second, since all ContentView-based widgets use a databound control, like RadListView for displaying the list of items on the frontend, we could easily subscribe to the ItemDataBound event of the list view, and get access to each item that gets bound, and to its properties.
For the current blog post, let's take the News widget for example. We can copy its default template for TitlesDatesSummariesListView and paste the HTML in a new UserControl.
Then, while still on the presentational part, we can define a placeholder to display our category links. For example a label:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TitlesDatesSummariesListViewCategoryLinks.ascx.cs" Inherits="SitefinityWebApp.CustomTemplates.News.Frontend.TitlesDatesSummariesListViewCategoryLinks" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.ContentUI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.Comments" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI" Assembly="Telerik.Sitefinity" %>
<%@ Register TagPrefix="telerik" Namespace="Telerik.Web.UI" Assembly="Telerik.Web.UI" %>
<%@ Register TagPrefix="sf" Namespace="Telerik.Sitefinity.Web.UI.PublicControls.BrowseAndEdit" Assembly="Telerik.Sitefinity" %>
<
telerik:RadListView
ID
=
"NewsList"
ItemPlaceholderID
=
"ItemsContainer"
runat
=
"server"
EnableEmbeddedSkins
=
"false"
EnableEmbeddedBaseStylesheet
=
"false"
>
<
LayoutTemplate
>
<
sf:ContentBrowseAndEditToolbar
ID
=
"MainBrowseAndEditToolbar"
runat
=
"server"
Mode
=
"Add"
></
sf:ContentBrowseAndEditToolbar
>
<
ul
class
=
"sfnewsList sfnewsListTitleDateSummary"
>
<
asp:PlaceHolder
ID
=
"ItemsContainer"
runat
=
"server"
/>
</
ul
>
</
LayoutTemplate
>
<
ItemTemplate
>
<
li
class
=
"sfnewsListItem"
>
<
h2
class
=
"sfnewsTitle"
>
<
sf:DetailsViewHyperLink
ID
=
"DetailsViewHyperLink1"
TextDataField
=
"Title"
ToolTipDataField
=
"Description"
runat
=
"server"
/>
</
h2
>
<
div
class
=
"sfnewsMetaInfo"
>
<
sf:FieldListView
ID
=
"PublicationDate"
runat
=
"server"
Format
=
"{PublicationDate.ToLocal():MMM dd, yyyy}"
/>
</
div
>
<
sf:FieldListView
ID
=
"summary"
runat
=
"server"
Text
=
"{0}"
Properties
=
"Summary"
WrapperTagName
=
"div"
WrapperTagCssClass
=
"sfnewsSummary"
/>
<
sf:DetailsViewHyperLink
ID
=
"FullStory"
Text="<%$ Resources:NewsResources, FullStory %>" runat="server" CssClass="sfnewsFullStory" />
<
br
/><
sf:SitefinityLabel
Id
=
"CategoriesLabel"
runat
=
"server"
></
sf:SitefinityLabel
>
<
sf:ContentBrowseAndEditToolbar
ID
=
"BrowseAndEditToolbar"
runat
=
"server"
Mode
=
"Edit,Delete,Unpublish"
></
sf:ContentBrowseAndEditToolbar
>
</
li
>
</
ItemTemplate
>
</
telerik:RadListView
>
<
sf:Pager
id
=
"pager"
runat
=
"server"
></
sf:Pager
>
<
asp:PlaceHolder
ID
=
"socialOptionsContainer"
runat
=
"server"
/>
Then we can move to our new UserControl's code-behind part, to implement our business logic.
First, we need to subscribe to the ItemDataBound event of our RadListView control:
protected
void
Page_Load(
object
sender, EventArgs e)
{
//subscribe to the ItemDataBound event of the RadListView control that displays the news items
NewsList.ItemDataBound +=
new
EventHandler<Telerik.Web.UI.RadListViewItemEventArgs>(NewsList_ItemDataBound);
}
Next we have to get the actual Sitefinity content item that is being passed as parameter to the
ItemDataBound
event:void
NewsList_ItemDataBound(
object
sender, Telerik.Web.UI.RadListViewItemEventArgs e)
{
switch
(e.Item.ItemType)
{
case
RadListViewItemType.DataItem:
case
RadListViewItemType.AlternatingItem:
var listViewDataItem = (RadListViewDataItem)e.Item;
//get the actual news item that's currently bound to the ListView
var dataItem = (NewsItem)listViewDataItem.DataItem;
We also need to get a reference to our control that is going to display the desired categories links, and set its value:
if
(dataItem !=
null
)
{
//get our control that displays the Categories
var placeholder = e.Item.FindControl(
"CategoriesLabel"
)
as
SitefinityLabel;
//and render the categories as clickable links
placeholder.Text = RenderHierarchicalTaxaAsLink(dataItem,
"Category"
);
}
Inside the
RenderHierarchicalTaxaAsLink
we are passing the Sitefinity Content item that we resolved in the ItemDataBoundEvent and this will allow us to easily get the list of taxa assigned to it:public
string
RenderHierarchicalTaxaAsLink(NewsItem newsitem,
string
taxonomyFieldName)
{
var catList =
""
;
var itemsToTake = 10;
//get the Categories assigned to this news item
var categories = newsitem.GetValue<TrackedList<Guid>>(taxonomyFieldName).Take(itemsToTake);
Please note the
itemsToTake
parameter - it controls the maximum number of categories per item that we are going to display. As resolving each category makes a call to the database, we've set that number to 10 intentionally .Once we have the list of assigned categories what we need to do is load each category, as we currently have only its ID. We can then simply iterate through the list of category IDs, load each category and then using its own Name, the name of the Taxonomy it belongs to and the name of the single Taxon from that Taxonomy we can construct the filtering URL parameter in a similar fashion: -in-Category/Categories/yourCategoryName . This is the default format our Sitefinity TaxonomyEvaluator is looking for, and it will ensure us the correct filtering behavior. The finishing stop is to combine this with the absolute URL of the page we're currently on and we end up with something like:
if
(categories !=
null
&& categories.Count() > 0)
{
catList =
"Categories:</br> "
;
//get the page URL
var currentUrl = HttpContext.Current.Request.Url.ToString();
if
(!HttpContext.Current.Request.Url.Query.IsNullOrEmpty())
currentUrl = currentUrl.Replace(HttpContext.Current.Request.Url.Query,
string
.Empty);
if
(currentUrl.EndsWith(
"/"
))
currentUrl = currentUrl.TrimEnd(
'/'
);
var taxManager = TaxonomyManager.GetManager();
//load the categories and build their filter URL to construct the clickable links
foreach
(var cat
in
categories)
{
var t = taxManager.GetTaxon<HierarchicalTaxon>(cat);
var url =
string
.Format(
"{0}/-in-{1}/{2}/{3}"
, currentUrl, t.Taxonomy.TaxonName, t.Taxonomy.Name, t.Name);
var link =
string
.Format(
"<a href='{0}'>{1}</a><br/>"
, url, t.Name).ToString();
catList = catList + link;
}
}
return
catList;
With this our job on the custom template is complete - simply build the project and then proceed with specifying the path to the custom template in your widget's advanced settings TemplatePath property, so it will start using the custom template instead of the default one.
For your convenience you can find the complete sample of the custom template attached to this blog post:
CustomTemplates - displaying the categories as clickable links
As an end result you should have the categories you've assigned each item to, displayed as click-able links under each item in the ListView.
A short video demonstrating this functionality can be found here.
As a bottom line I just wanted to point out that although the sample demonstrates achieving this functionality with a News widget, you should be aware of the fact that the approach is pretty much universal, so it can be very easily adapted to any other ContentView based widget if you follow the described steps.
I hope you enjoyed this post, please keep in touch for more useful tips and tricks that can help you customize the product behavior.
Boyan Barnev
Boyan Barnev is a Principal Information Developer at Progress. His mission is to demonstrate the unlimited capabilities of Sitefinity CMS via product documentation, SDK samples, and technical blog posts. He has graduated from the American University in Bulgaria and joined Telerik in 2011. Since then Boyan has held various positions in the company, leading the strategy and operation of the Sitefinity CMS Technical support service worldwide.