TagHelpers are a great new feature in ASP.NET Core, allowing you to create and render html elements using server side code. In other words, you can write html like markup for the html helpers. You can provide robust, maintainable, reusable code with information provided on the server. ASP.NET Core Documentation is good starting point to learn about fundamentals of TagHelpers. In this blog series, we'll see how to create TagHelpers for various jQueryUI widgets and Bootstrap components. Let's look at how to create an advanced TagHelper using jQuery UI AutoComplete widget.

Infrastructure

  • Create a new ASP.NET web application using the ASP.NET Core (aka ASPNET5) project template inside Visual Studio 2015.
  • Name the project MVCCustomTagHelpers
  • Add a folder named Helpers. The custom TagHelpers will reside in this folder.

AutoComplete TagHelper

  • Add a new class named "AutoCompleteTagHelper" in the Helpers folder.
  • Import the following namespaces in the class:
using System.Collections.Generic;  
using Microsoft.AspNet.Razor.TagHelpers;  
using System.Text;

Inherit the TagHelper class, which is the base class for all TagHelpers. We want to apply the TagHelper on "auto-complete" html element, so decorate the class with HtmlTargetElement attribute.


[HtmlTargetElement("auto-complete")]  
public class AutoCompleteTagHelper : TagHelper  
{  
}  

To use jQuery autocomplete, we need to initialise the widget over a html tag. The minimum option we need to set is the "source"—source binds the autocomplete to the array of data. We'll declare some properties for the autocomplete TagHelper, like ID, ItemsSource, and MinLength.


[HtmlTargetElement("auto-complete")]  
public class AutoCompleteTagHelper : TagHelper  
{  
//Attributes declaration  
private const string IdAttributeName = "id";  
private const string SourceAttributeName = "items-source";  
private const string MinLengthAttributeName = "min-length";  

[HtmlAttributeName(IdAttributeName)]  
public string Id { get; set; }  

[HtmlAttributeName(SourceAttributeName)]  
public List ItemsSource { get; set; } = null;  

[HtmlAttributeName(MinLengthAttributeName)]  
public int MinLength { get; set; } = 0;  
}  

Next, we need to define the behavior of TagHelper by overriding the Process method of the base TagHelper class. In this method, autocomplete jQuery UI initialization script is created, and values assigned per the properties described above. The ItemsSource is converted to an array and set to the source property of AutoComplete.


public override void Process(TagHelperContext context, TagHelperOutput output)  
{  
output.TagName = "";  
var sb = new StringBuilder();  
//HTML  
sb.AppendLine("");  
// Script for converting html input into JQuery-UI autocomplete  
sb.AppendLine("// ");  
            sb.AppendLine("$(\\"#" + Id + "\\").autocomplete({");              
            if (ItemsSource != null && ItemsSource.Count > 0)  
            {  
                sb.AppendLine("source: ");  
                sb.Append("[");  
                for (int i = 0; i < ItemsSource.Count; i++)  
                {  
                    sb.Append(i == 0 ? "\\"" + ItemsSource[i].ToString() + "\\"" : ", \\"" + ItemsSource[i].ToString() + "\\"");  
                }  
                sb.Append("]");  
            }  
            sb.Append(string.Format(", minLength: {0}", MinLength));  
            sb.AppendLine("});");  
            sb.AppendLine("  
// ]]>");  
//Add HTML and script code to output  
output.Content.AppendHtml(sb.ToString());  
}  

Complete AutoCompleteTagHelper Class


using System.Collections.Generic;  
using Microsoft.AspNet.Razor.TagHelpers;  
using System.Text;  

namespace MVC6CustomTagHelper.Helpers  
{  
//TagHelper's Element declaration  
[HtmlTargetElement("auto-complete")]  
public class AutoCompleteTagHelper : TagHelper  
{  
//Attributes declaration  
private const string IdAttributeName = "id";  
private const string SourceAttributeName = "items-source";  
private const string MinLengthAttributeName = "min-length";  

[HtmlAttributeName(IdAttributeName)]  
public string Id { get; set; }  

[HtmlAttributeName(SourceAttributeName)]  
public List ItemsSource { get; set; } = null;  

[HtmlAttributeName(MinLengthAttributeName)]  
public int MinLength { get; set; } = 0;  

//Add behaviour for the TagHelper  
public override void Process(TagHelperContext context, TagHelperOutput output)  
{  
output.TagName = "";  
var sb = new StringBuilder();  
//HTML  
sb.AppendLine("");  
// Script for converting html input into JQuery-UI autocomplete  
sb.AppendLine("// ");  
            sb.AppendLine("$(\\"#" + Id + "\\").autocomplete({");              
            if (ItemsSource != null && ItemsSource.Count > 0)  
            {  
                sb.AppendLine("source: ");  
                sb.Append("[");  
                for (int i = 0; i < ItemsSource.Count; i++)  
                {  
                    sb.Append(i == 0 ? "\\"" + ItemsSource[i].ToString() + "\\"" : ", \\"" + ItemsSource[i].ToString() + "\\"");  
                }  
                sb.Append("]");  
            }  
            sb.Append(string.Format(", minLength: {0}", MinLength));  
            sb.AppendLine("});");  
            sb.AppendLine("  
// ]]>");  
//Add HTML and script code to output  
output.Content.AppendHtml(sb.ToString());  
}  
}  
}  

Application

Save and Rebuild the project. In the _ViewImports.cshtml we need to add a reference to the custom tag helpers in the current assembly using the @addTagHelper command.


@addTagHelper "*, MVCCustomTagHelpers"  

Open _Layout.cshtml and add the CDN references for jQuery and jQueryUI inside the head tag. Make sure the View is using the _Layout.cshtml, alternatively you can add the CDN references to your view page too.

<link href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript" src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

In the view, we can now use the AutoComplete TagHelper. You should also get IntelliSense as you type. For example, if the model returns a list of languages, we can declare the auto-complete TagHelper as follows:

 <auto-complete id="ac1" items-source="@Model.LangList"></auto-complete>

Run the application and type a letter. AutoComplete TagHelper AutoComplete TagHelper