Добавить класс CSS в элемент html в TagHelper

В ASP.NET Core View у меня есть следующее:

<div class="message" message=""></div>

И я использую Tag Helper со следующим TagHelper:

[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);
    }
  }
}

В следующей строке кода мне нужно добавить «активный» в качестве класса CSS.

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

Однако это ничего не дает. Сообщение остается только с классом "сообщение".

Что мне не хватает?


person Miguel Moura    schedule 26.10.2016    source источник


Ответы (4)


Начиная с ASP.NET Core 2.1 вы можете использовать TagHelperOutputExtensions, предоставленный Microsoft, чтобы добавить ваш "активный" класс CSS в одну строку кода.

using Microsoft.AspNetCore.Mvc.TagHelpers;
using System.Text.Encodings.Web;
...
public override void Process(TagHelperContext context, TagHelperOutput output)
{
    ...
    output.AddClass("active", HtmlEncoder.Default);
    ...
}
person Mathew Leger    schedule 23.08.2018

Ответ @Shyju в основном правильный, но есть много лишнего кода, который не нужен. Для обработки в ASP.NET Core 2.0 достаточно следующего:

var classes = output.Attributes.FirstOrDefault(a => a.Name == "class")?.Value;
output.Attributes.SetAttribute("class", $"active {classes}");
person Chris Pratt    schedule 08.12.2017
comment
хорошо! но это не проверяет повторяющиеся значения, если класс уже содержит новые значения для добавления. Итак, я публикую более полную версию здесь - person S.Serpooshan; 12.08.2018

Я думаю, вам следует удалить существующий класс TagHelperAttribute для css из коллекции атрибутов и добавить новый, в котором есть все классы (существующий и ваш новый «активный» класс)

Приведенный ниже код должен работать.

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);
person Shyju    schedule 26.10.2016
comment
FYI output.Attributes.Remove(existingClass); должен находиться внутри оператора if, иначе он пытается удалить нулевое значение. - person Josh Schultz; 07.07.2017
comment
existingClass.Value.ToString() не будет работать, так как existingClass.Value имеет тип Microsoft.AspNetCore.Mvc.TagHelpers.TagHelperOutputExtensions.ClassAttributeHtmlContent класс. - person Sergey; 15.10.2017
comment
Чтобы быть точным, это будет работать, если есть только одно имя класса. Но не для 2 или более, например ‹div class=message text›‹/div› не будет возвращать классы в ToString(). - person Sergey; 15.10.2017
comment
Мой пример выше с ‹div../› неверен. На самом деле метод .ToString() отлично работает, если не было вспомогательных тегов, которые добавляли дополнительные классы через вывод. Attributes.Add(class, ...) перед вызовом нашего помощника по тегам. Если да, то метод .ToString() не будет возвращать ожидаемые имена классов css. Он вернет ClassAttributeHtml‌​Content имя класса C# вместо ASP.NET Core 2. - person Sergey; 15.10.2017
comment
да. Не было встроенной поддержки нескольких классов. Для этого был добавлен новый метод расширения (AddClasses). Я обновлю ответ этим, когда поиграюсь с ним позже. - person Shyju; 15.10.2017
comment
Боже, о боже, это УЖАСНО, что мы должны сделать это таким образом. Я буду писать метод расширения, чтобы значительно облегчить эту боль, но мне интересно, почему команда не видит здесь Need for Simplicity®. - person Nicholas Petersen; 22.11.2017

Другие ответы здесь не проверяют текущий класс 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);

    }

}
person S.Serpooshan    schedule 12.08.2018