CodeDigest.Com Logo
Featured:

Creating Custom Tag Helpers in Asp.Net Core MVC

Tagged as: Asp.Net Core Asp.Net Core MVC Posted By

Tag Helpers is a new feature added in Asp.Net Core MVC framework that helps in extending the HTML elements capabilities in MVC views. Read my previous article Understanding Tag Helpers in Asp.Net Core MVC to understand about tag helpers and some of the most used inbuilt tag helpers in Asp.Net Core MVC.

Asp.Net Core MVC also allows developers to write custom tag helpers by extending TagHelper class. To create a custom tag helpers, we need to create a custom tag helper class by inheriting the TagHelper class found in Microsoft.AspNetCore.Razor.TagHelpers namespace and override the Process() method to add behaviour for the  targeting html element. The TagHelper class also expose asynchronous version of Process() method called ProcessAsync() for asynchronous tag helpers.

The signature of Process() method is,

 

void Process(TagHelperContext context, TagHelperOutput output)

 

The TagHelperOutput class will give us access to the target html element to manipulate the html content. This class expose the following properties which can be used to manipulate the HTML element.

 

public TagHelperContent PostElement { get; }

public TagHelperContent PostContent { get; }

public TagHelperContent Content { get; set; }

public TagHelperContent PreContent { get; }

public TagHelperContent PreElement { get; }

 

As the name of properties suggests, we can add HTML elements and contents in and around the target elements. Refer here to know more about other properties and methods of this class.

The TagHelperContext class gives information about the target html element we are manipulating.

AllAttributes – A Read only dictionary of all the HTML elements attributes.

Items – Returns dictionary of TagHelpers applied to an element for co-ordination.

UniqueId – Returns unique id of the target element.

With this information, let’s move ahead and create custom tag helper class.

For easy understanding, let’s create 2 simple custom tag helpers in this article, a Button tag helper and a Input tag helper. The first tag helper will help us add a bootstrap glyphicon in addition to the text value for a button element. For example, let’s add a tag helper attribute to button element called glyphs-icon and pass the icon's css class found here. Refer below.

 

<button type="submit" class="btn btn-default" glyphs-icon="floppy-disk">Register</button>

 

The above tag helper will produce the following HTML and browser output.

 

<button type="submit" class="btn btn-default"><i class="glyphicon glyphicon-floppy-disk"></i> Register</button>

 

To create custom tag helper classes, let’s add a folder called Infrastructure in our Asp.Net Core MVC solution.

 

Button with GlyphIcons

Add a class file under Infrastruture folder and name it as ButtonTagHelper.cs. We will inherit the class with TagHelper class and override the Process() method. The final code below.

public class ButtonTagHelper : TagHelper
{
    public string GlyphsIcon { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        TagBuilder icon = new TagBuilder("i");
        icon.AddCssClass($"glyphicon glyphicon-{GlyphsIcon}");
        output.PreContent.AppendHtml(icon);
        output.PreContent.AppendHtml(" ");
    }
}
   

The custom tag helper class expose a public property called GlyphsIcon to set the css class of the glyphicon from the target element. We use TagBuilder class defined in Microsoft.AspNetCore.Mvc.Rendering namespace for building html tag. Since, we need the icon to be placed before the actual content of the button text, the above code adds this html element using PreContent property.

Using the Custom Tag Helper

To use the Tag helper we need to expose the custom tag helper class for the views. We can either include it in specific view file or _ViewImports.cshtml file by including the below statement.

 

@addTagHelper CustomTagHelpersDemo.Infrastructure.*, CustomTagHelpersDemo

 

When you execute the application you can see the glyphicon appearing with button content similar to above image.

One thing to note here is, we never said anywhere in the code about the target html element for the tag helper class to apply. MVC refers it by convention i.e. in this case, since our class name is ButtonTagHelper (target element name+TagHelper) MVC automatically applies to all Button elements in the view. Similarly, if the name is InputTagHelper it will apply to all input html elements. The visual studio also provided intellisense support to add the custom tag helper attribute in the target elements.

MVC also automatically converts the HTML attribute name glyphs-icon with hyphen to C# custom tag helper attribute GlyphsIcon.

Restricting Scope of Custom Tag Helpers

Most of the times, we will not apply a custom tag helpers to all the matching HTML elements in the project. We can restrict the scope of custom tag helpers using HtmlTargetElement attribute. We can decorate the ButtonTagHelper class with this attribute to apply only to button element with glyphs-icon property and only if the button is placed inside a div tag. Refer the below HtmlTargetElement attribute usage for this.

 

[HtmlTargetElement("button", Attributes = "glyphs-icon", ParentTag = "div")]

public class ButtonTagHelper : TagHelper

 

Input Elements with UI Hints

In previous section, we have inserted html contents inside the target element using PreContent property of TagHelperOutput class. Let’s now add another custom tag helper to add pre and post elements to a target HTML element. For example, we will add some hints and icons for input text box to infer the data it supports similar to below.

The below custom tag helper class will do that.

 

[HtmlTargetElement("input", Attributes = "input-type", ParentTag = "div")]
public class TextBoxTagHelper : TagHelper
{
    public string InputType { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        TagBuilder preDiv = new TagBuilder("div");
        TagBuilder postDiv = new TagBuilder("div");
        preDiv.AddCssClass("input-group-addon");
        postDiv.AddCssClass("input-group-addon");

        switch (InputType)
        {
            case "Amount":
                preDiv.InnerHtml.Append("$");
                postDiv.InnerHtml.Append(".00");
                break;
            case "Email":
                preDiv.InnerHtml.Append("@");
                postDiv.InnerHtml.Append(".com");
                break;
            case "UserName":
                TagBuilder glyUserIcon = new TagBuilder("i");
                glyUserIcon.AddCssClass("glyphicon glyphicon-user");
                preDiv.InnerHtml.AppendHtml(glyUserIcon);
                break;
            case "Phone":
                TagBuilder glyPhIcon = new TagBuilder("i");
                glyPhIcon.AddCssClass("glyphicon glyphicon-phone-alt");
                preDiv.InnerHtml.AppendHtml(glyPhIcon);
                postDiv.InnerHtml.Append("##");
                break;
            default:
                TagBuilder glyTextIcon = new TagBuilder("i");
                glyTextIcon.AddCssClass("glyphicon glyphicon-pencil");
                preDiv.InnerHtml.AppendHtml(glyTextIcon);
                break;
        }           

        output.PreElement.AppendHtml(preDiv);
        output.PostElement.AppendHtml(postDiv);

    }
}


 

The HtmlTargetElement attribute will apply the tag helper only for those elements with input-type property and input elements defined under a div tag. The razor view code using the above custom tag helper is below.

 

<form class="form-inline">

    <div class="form-group col-md-3">

        <div class="input-group">

            <input type="text" input-type="UserName" class="form-control" id="exampleInputAmount0" placeholder="UserName" />

        </div>

    </div>

    <div class="form-group col-md-3">

        <div class="input-group">

            <input type="text" input-type="Amount" class="form-control" id="exampleInputAmount1" placeholder="Amount" />

        </div>

    </div>

    <div class="form-group col-md-3">

        <div class="input-group">

            <input type="text" input-type="Email" class="form-control" id="exampleInputAmount2" placeholder="Email" />

        </div>

    </div>

    <div class="form-group col-md-3">

        <div class="input-group">

            <input type="text" input-type="Phone" class="form-control" id="exampleInputAmount3" placeholder="Phone" />

        </div>

    </div>

</form>

 

Further Reading

  1. Read Difference Between Asp.Net and Asp.Net Core for a side by side difference.
  2. To know more about the new features in Asp.Net Core, read Breaking Changes and New Features of Asp.Net Core MVC.


Feedback

Comments