ASP.NET Core MVC – Tag Helper Components

This entry is part 5 of 5 in the ASP.NET Core Tag Helpers series

Tag Helper Components – Introduction

We already talked about Tag Helpers in several posts before. This time we will be talking about something related.

ASP.NET Core 2 is here and it brings us a new feature – Tag Helper Components.

Tag Helper Components are responsible for generating or modifying a specific piece of HTML. They work in conjunction with Tag Helpers.

To be precise Tag Helpers will run your Tag Helper Components.

Tag Helper Components are perfect for dynamically adding content to your HTML.

To have your Tag Helper Component execute you need to have a specific Tag Helper set up. This Tag Helper needs to inherit from the built-in abstract class: TagHelperComponentTagHelper.

I know, I know, the naming is confusing.

A class that inherits from TagHelperComponentTagHelper will be a Tag Helper that will execute matching Tag Helper Components.

The process

We start by creating a new Tag Helper Component. We can also use built-in Tag Helper Components that are targeting head and body tags. After, we can make use of Tag Helper Components by writing Tag Helpers that inherit from the special class – TagHelperComponentTagHelper.

Let’s see an example.

I will start by creating new Razor Pages template:

dotnet new razor

Things we have to do to get a Tag Helper Component working:

  1. Create a new Tag Helper Component
  2. Inject it via DI
  3. Create a new Tag Helper class that inherits from TagHelperComponentTagHelper class
  4. Include the Tag Helper in _ViewImports.cshtml file

 

Creating the Tag Helper Component:

public class ArticleTagHelperComponent : TagHelperComponent
{
    public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (string.Equals(context.TagName, "article", StringComparison.OrdinalIgnoreCase))
        {
            output.PostContent.AppendHtml("<script>console.log('ASP.NET Core - Love From Console');</script>");
        }


        return Task.CompletedTask;
    }
}

 

If you worked with Tag Helpers then this will feel familiar. In this case, we inherit from a built-in abstract TagHelperComponent class and then we override the ProcessAsync method.

We need to make Tag Helper Component part of our app.  We do that by injecting it to services container:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ITagHelperComponent, ArticleTagHelperComponent >();

    services.AddMvc();
}

 

Now we can make use of our TagHelper Component!

Creating the Tag Helper:

[HtmlTargetElement("article")]
[EditorBrowsable(EditorBrowsableState.Never)]
public class ArticleTagHelperComponentTagHelper : TagHelperComponentTagHelper
{
    public CodingBlastTagHelper(ITagHelperComponentManager componentManager, ILoggerFactory loggerFactory)
        : base(componentManager, loggerFactory)
    {
    }
}

Notice the first line, this Component Tag Helper will target all article elements/tags in your HTML.

For our app to be aware of this Tag Helper we have to add it inside of _ViewImports.cshtml file:

@using IntroTagHelperComponent
@namespace IntroTagHelperComponent.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper SampleTagHelperComponent.ArticleTagHelperComponentTagHelper, SampleTagHelperComponent

 

To actually see this in action we need to have at least one article tags in our code. So, I will modify the Index.cshtml page:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div></div>

<article>
    TagHelperComponent will add stuff here.
</article>

 

Built-in Tag Helpers for Tag Helper Components

There are currently two built-in Tag Helpers that inherit from TagHelperComponentTagHelper class. They are located in Microsoft.AspNetCore.Mvc.TagHelpers assembly.

Those two Tag Helpers are HeadTagHelper and BodyTagHelper. They enable us to inject things into head and body quite easily. All we have to do is to create Tag Helper Component and inject it to our app.

Here is the code for HeadTagHelper (from aspnet/Mvc GitHub repository):

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.ComponentModel;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Logging;

namespace Microsoft.AspNetCore.Mvc.Razor.TagHelpers
{
    /// <summary>
    /// A <see cref="TagHelperComponentTagHelper"/> targeting the &lt;head&gt; HTML element.
    /// </summary>
    [HtmlTargetElement("head")]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public class HeadTagHelper : TagHelperComponentTagHelper
    {
        /// <summary>
        /// Creates a new <see cref="HeadTagHelper"/>.
        /// </summary>
        /// <param name="manager">The <see cref="ITagHelperComponentManager"/> which contains the collection
        /// of <see cref="ITagHelperComponent"/>s.</param>
        /// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
        public HeadTagHelper(ITagHelperComponentManager manager, ILoggerFactory loggerFactory)
            : base(manager, loggerFactory)
        {
        }
    }
}

The code is quite simple. It inherits from the TagHelperComponentTagHelper class and targets head HTML element.

If you check out the default _ViewImports.cshtml file content you will see that these will be included by default:

@using IntroTagHelperComponent
@namespace IntroTagHelperComponent.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

We can have built-in HeadTagHelper user our custom Tag Helper Component for the head tags:

We will add a Tag Helper component that will check all head tags:

public class HeadTagHelperComponent : TagHelperComponent
{
    public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (string.Equals(context.TagName, "head", StringComparison.OrdinalIgnoreCase))
        {
            output.PostContent.AppendHtml("<script>console.log('head tag');</script>");
        }

        return Task.CompletedTask;
    }
}

 

Of course, we need to add HeadTagHelperComponent to our app:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ITagHelperComponent, HeadTagHelperComponent>();

    services.AddMvc();
}

 

Code

Code example is available on GitHub – SampleTagHelperComponent

 

Summary

  • Tag Helper Components are useful for dynamically adding content to your HTML
  • Special Tag Helpers (that inherit from TagHelperComponentTagHelper class) will execute all matching Tag Helper Components


ASP.NET Core Tag Helpers Series Navigation: Previous post: << ASP.NET Core MVC – Custom Tag Helpers
Next post:



Ibrahim Šuta

Software Consultant interested and specialising in ASP.NET Core, C#, JavaScript, Angular, React.js.