在TagHelper中为HTML元素添加CSS类

23
在ASP.NET Core视图中,我有以下内容:
<div class="message" message=""></div>

我使用以下TagHelper作为a标签助手:

[HtmlTargetElement("div", Attributes = MessageName)]
public class MessageTagHelper : TagHelper {

  private const String MessageName = "message";

  [HtmlAttributeName(MessageName)]
  public String Message { get; set; }

  [HtmlAttributeNotBound, ViewContext]
  public ViewContext ViewContext { get; set; }


  public override void Process(TagHelperContext context, TagHelperOutput output) {

    String message;
    Boolean defined = ViewContext.HttpContext.Request.Cookies.TryGetValue("_message", out message);

    if (defined) {
      ViewContext.HttpContext.Response.Cookies.Delete("_message");
      output.Attributes.Add("class", "active");
      output.Content.Append(message);
    }
  }
}

在下面的代码行中,我需要将"active"作为CSS类添加。

output.Attributes.Add("class", "active");

然而,这并没有起到任何作用。消息仍然只有"class"为"message"。

我错过了什么?

4个回答

44
从 ASP.NET Core 2.1 开始,您可以使用由 Microsoft 提供的 TagHelperOutputExtensions 类,在一行代码中添加您的“active”CSS类。
using Microsoft.AspNetCore.Mvc.TagHelpers;
using System.Text.Encodings.Web;
...
public override void Process(TagHelperContext context, TagHelperOutput output)
{
    ...
    output.AddClass("active", HtmlEncoder.Default);
    ...
}

7

@Shyju的答案大多是正确的,但是有很多不必要的冗余代码。下面的内容足以在ASP.NET Core 2.0中处理它:

var classes = output.Attributes.FirstOrDefault(a => a.Name == "class")?.Value;
output.Attributes.SetAttribute("class", $"active {classes}");

很好!但是,如果类中已经包含要添加的新值,则此代码不会检查重复值。因此,我在这里发布了更完整的版本。 - S.Serpooshan

2

其他答案没有检查当前的CSS类,以避免重复的值。在这里,我编写了一个扩展程序,添加了一个带有适当检查的CSS类,以确保输出干净的HTML:

public static class GeneralExtionsions
{
    //the white space chars valid as separators between every two css class names
    static readonly char[] spaceChars = new char[] { ' ', '\t', '\r', '\n', '\f' };

    /// <summary> Adds or updates the specified css class to list of classes of this TagHelperOutput.</summary>
    public static void AddCssClass(this TagHelperOutput output, string newClass)
    {
        //get current class value:
        string curClass = output.Attributes["class"]?.Value?.ToString(); //output.Attributes.FirstOrDefault(a => a.Name == "class")?.Value?.ToString();

        //check if newClass is null or equal to current class, nothing to do
        if (string.IsNullOrWhiteSpace(newClass) || string.Equals(curClass, newClass, StringComparison.OrdinalIgnoreCase))
        {
            return;
        }

        //append newClass to end of curClass if curClass is not null and does not already contain newClass:
        if (!string.IsNullOrWhiteSpace(curClass) 
            && curClass.Split(spaceChars, StringSplitOptions.RemoveEmptyEntries).Contains(newClass, StringComparer.OrdinalIgnoreCase)
            )
        {
            newClass = $"{curClass} {newClass}";
        }

        //set new css class value:
        output.Attributes.SetAttribute("class", newClass);

    }

}

2
我认为你应该从Attributes集合中删除现有的用于css类的TagHelperAttribute,并添加一个新的TagHelperAttribute,其中包含所有类(现有类和新的“active”类)。
下面的代码应该可以工作。
var existingClass = output.Attributes.FirstOrDefault(f => f.Name == "class");
var cssClass = string.Empty;
if (existingClass != null)
{
    cssClass = existingClass.Value.ToString();       
}
cssClass = cssClass + " active";
var ta = new TagHelperAttribute("class", cssClass);
output.Attributes.Remove(existingClass);
output.Attributes.Add(ta);

1
请注意,output.Attributes.Remove(existingClass); 应该放在 if 语句内部,否则它会尝试删除一个空值。 - Josh Schultz
"existingClass.Value.ToString()" 不起作用,因为 "existingClass.Value" 是类型为 "Microsoft.AspNetCore.Mvc.TagHelpers.TagHelperOutputExtensions.ClassAttributeHtmlContent" 的类。 - Serg
准确地说,如果只有一个类名,它将起作用。但是对于两个或更多的类名,则不适用,例如<div class="message text"></div>在ToString()中不会返回类。 - Serg
我上面的例子中使用 <div../> 是不正确的。实际上,如果没有标签助手通过 output. Attributes.Add("class", ...) 添加了一些额外的类,则方法 .ToString() 就可以正常工作。如果它们确实这样做了,那么方法 .ToString() 将不会返回预期的 CSS 类名称。在 ASP.NET Core 2 中,它将返回 "ClassAttributeHtmlContent" C# 类名。 - Serg
是的。没有内置支持多个类的功能。现在添加了一个新的扩展方法(AddClasses)来处理这个问题。稍后我会尝试一下并更新答案。 - Shyju
2
这真是太丑陋了,我们必须以这种方式来做。我将编写一个扩展方法来大大减轻这种痛苦,但我想知道为什么团队看不到简单性的需求®。 - Nicholas Petersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接