An easy Taghelper to make an element ‘active’ when clicked using Razor.0 Reacties

Still using backend HTML logic.

ASP.NET Core makes things a lot more easier for us, backend developers. Though, accent today, is more on frontend development, still, for reasons of security for instance, backend state management is still used.

Now take a look at this tiny gem, a TagHelper.

A ‘which menu has been clicked-set-active-helper’

What it does, basically, is checking if a

  • element has an attribute activecheck. If so, it detects which ‘action-route’ was executed/is executing and if the name matches, it adds class=”active”. So the output will be  e.g.
  • active”>Home
  • e.g. in the Razor View I have:


                                           <li activecheck="true" data-menu="Index" >
                                                <a asp-controller="Home" asp-action="Index">Homea>
                                           

      I had to add a ‘data-menu’ attribute, because Taghelpers, can not, as far as I found, parse the raw Razor Markup, when using ‘GetChildContentAsync()’  for instance, it only gets the HTML output that’s already there, without Razor markup. So, I cannot parse the child anchor and retrieve asp-acction=”Index”.
      Therefore, I specify it again using data-menu=”Index”. Note, this is removed later by the taghelper.

      using Microsoft.AspNetCore.Html;
      using Microsoft.AspNetCore.Mvc.Controllers;
      using Microsoft.AspNetCore.Mvc.Infrastructure;
      using Microsoft.AspNetCore.Razor.TagHelpers;

      namespace ladidah.TagHelpers
      {
          [HtmlTargetElement("li", Attributes = "activecheck")]
          public class LiActiveHelper: TagHelper
          {
              public bool activecheck { get; set; }
              private readonly string menu;
              public LiActiveHelper(IActionContextAccessor httpContext)
              {
                  var currentRoute = (ControllerActionDescriptor)httpContext.ActionContext.ActionDescriptor;
                  menu = currentRoute.ActionName;
              }
              public override void Process(TagHelperContext context, TagHelperOutput output)
              {
                  if (activecheck)
                  {
                      var dataMenu = output.Attributes["data-menu"];
                   
                       if (dataMenu != null && dataMenu.Value is HtmlString str && str.Value == menu)
                      {
                          output.Attributes.RemoveAll("activecheck");
                          output.Attributes.RemoveAll("data-menu");
                          if (!output.Attributes.ContainsName("class"))
                          {
                              output.Attributes.SetAttribute("class", "active");
                          }
                      }               
                  }          
              }
          }
      }

      To activate this taghelper, I had to add the following line in my _ViewImports.cshtml file

      @addTagHelper ladidah.TagHelpers.LiActiveHelper, ladidah

      Benefit of IoC in ASP.NET Core.

      In my ConfigureServices method, in startup.cs I had to add the following line, in order to be able to get the action context of the current MVC Controller.

      public void ConfigureServices(IServiceCollection services)
             {

      // code removed for readability

        services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

      }

      I hope you find this snippet useful.