Tag-хэлперы в ASP.NET Core MVC. Управление выводом (TagHelperOutput)

Объект класса TagHelperOutput позволяет управлять выводом tag-хэлпера. До сих пор мы использовали объект этого класса в ограниченном виде — просто указывали html-тэг для хэлпера и содержимое этого тэга. В этой части мы более подробно познакомимся с классом TagHelperOutput

Свойства класса TagHelperOutput

Ниже представлены основные свойства класса TagHelperOutput, действие которых мы сегодня рассмотрим:

Attributes коллекция атрибутов, устанавливаемых у создаваемого элемента html
Content содержимое генерируемого элемента html в виде объекта TagHelperContent
PostContent содержимое, которое устанавливается после создаваемого элемента html
PostElement представляет html-элемент, который добавляется после создаваемого элемента html
PreContent представляет содержимое, которое устанавливается перед создаваемым элементом html
PreElement представляет html-элемент, который добавляется перед создаваемым элементом html
TagMode формат создаваемого элемента
TagName указывает, какой элемент html будет создаваться вместо тега хелпера

Для демонстрации работы этих свойств воспользуемся tag-хэлперами, разработанными ранее.

Формат элемента (свойство TagMode)

Свойство TagMode позволяет задать формат элемента tag-хэлпера и является перечислением следующего вида:

StartTagAndEndTag 0 html-элемент содержит и открывающий и закрывающий тэг
SelfClosing 1 html-элемент содержит один самозакрывающийся тег, например, <tag/>
StartTagOnly 2 html-элемент сдержит только открывающий тэг

Например, вернемся к нашим tag-хэлперам и посмотрим на хэлпер для вывода дня недели:

public class DayTagHelper: TagHelper
{
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "div";
        output.Content.SetContent($"Сегодня {DateTime.Now:dddd}");
    }
}

этот tag-хэлпер использует для генерации html-разметки строку с днем недели, поэтому такой тэг должен содержать в html-разметке и открывающий и закрывающий теги, то есть, свойство TagMode должно иметь значение StartTagAndEndTag, что, собственно, и сделано по умолчанию. Если же мы попробуем изменить это свойство так:

output.TagMode = TagMode.SelfClosing;

То в приложении вместо строки с днем недели мы получим вот такую html-разметку:

<div/>

Значение TagMode.SelfClosing стоит использовать только в том случае, если предполагается, что ваш tag-хэлпер не будет выводить никакой информации. В свою очередь, значение TagMode.StartTagOnly стоит использовать в том случае, если предполагается, что закрывающий тэг в html-разметке будет сгенерирован за пределами tag-хэлпера, например в другом хэлпере.

Управление содержимым (свойство Content)

Этим свойством мы уже пользовались. Однако, класс TagHelperContent которым и представлено свойство Content содержит ряд других методов, позволяющих управлять содержимым, а именно:

Append() Добавляет текст к существующему содержимому.
AppendHtml() Добавляет к существующему содержимому текст в формате html.
Clear() Очищает содержимое.
GetContent() Возвращает содержимое.
SetContent(String) Задает содержимое в виде текста.
SetHtmlContent() Задает содержимое в формате html.

Таким образом, используя свойства TagHelperOutput и методы TagHelperContent мы можем изменять содержимое html-разметки нашего tag-хэлпера. Для примера, воспользуемся tag-хэлпером, который мы создали в предыдущей части, вот как выглядит его код на данный момент:

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace AspNetMvcTagCreate.TagHelpers
{
    public class DayInfoTagHelper: TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var childContent = await output.GetChildContentAsync();
            string content = "<h3>День недели</h3>";
            output.TagName = "div";
            content += childContent.GetContent();
            output.Content.SetHtmlContent(content);            
        }
    }
}

В приложении этот tag-хэлпер генерирует следующую html-разметку:

<div><h3>День недели</h3>
    <div>Сегодня воскресенье</div>
    <div>Номер дня в году 330</div>
</div>

Изменим код tag-хэлпера следующим образом:

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
    var childContent = await output.GetChildContentAsync();
    output.TagName = "div";
    output.PreElement.AppendHtml("<div class=\"card\" style=\"width: 18rem;\">");
    output.PreElement.AppendHtml("<h5 class=\"card-title\">День недели</h5>");
    output.Content.SetHtmlContent(childContent.GetContent());
    output.PostElement.AppendHtml("</div>");
}

здесь мы добавляем перед содержимым тэга ещё один элемент div и заголовок h5 и после содержимого tag-хэлпера добавляем закрывающий тэг для div. В результате, мы получим следующую html-разметку:

<div class="card" style="width: 18rem;"><h5 class="card-title">День недели</h5><div>
    <div>Сегодня воскресенье</div>
    <div>Номер дня в году 330</div>
</div></div>

в браузере такая разметка будет выглядеть следующим образом:

Чтобы этот пример работал как предполагается, в вашем проекте должен быть подключен фреймворк Bootstrap. В шаблоне ASP.NET Core MVC он подключен по умолчанию

Установка атрибутов в html-разметке (свойство Attributes)

Предыдущий пример получился не совсем удачным с точки зрения генерируемой html-разметки. Зачем нам лишний элемент div? Свойство Attributes позволяет нам  устанавливать атрибуты генерируемого html-элемента и представляет собой объект класса TagHelperAttributeList, который содержит следующие методы:

Add(string name, object value) добавляет атрибут с именем name и значением value
RemoveAll(string name) удаляет все атрибуты с именем name
SetAttribute(string name, object value) устанавливает для атрибута с именем name значение value
Clear() удаляет все атрибуты

Перепишем наш пример с использованием свойства Attributes, избавившись тем самым, от лишнего div в разметке:

public class DayInfoTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        var childContent = await output.GetChildContentAsync();
        output.TagName = "div";
        output.Attributes.Add("class", "card");
        output.Attributes.Add("style", "width: 18rem;");
        string content = "<h5 class=\"card-title\">День недели</h5>" + childContent.GetContent();
        output.Content.SetHtmlContent(content);
    }
}

Теперь будет генерироваться следующая разметка:

<div class="card" style="width: 18rem;"><h5 class="card-title">День недели</h5>
    <div>Сегодня воскресенье</div>
    <div>Номер дня в году 330</div>
</div>

Атрибуты tag-хэлпера

Кроме того, что мы можем управлять атрибутами html-тэгов, наши tag-хэлперы также могут содержать свои атрибуты, которые, по сути, являются публичными свойствами класса хэлпера. Например, нам может потребоваться вывести свой текст вместо строки «Сегодня» в tag-хэлпере дня недели или задать свой стиль какого-либо элемента и т.д. Перепишем класс хэлпера для вывода дня недели следующим образом:

using Microsoft.AspNetCore.Razor.TagHelpers;

namespace AspNetMvcTagCreate.TagHelpers
{
    public class DayTagHelper: TagHelper
    {
        public string Prefix { get; set; } = "Сегодня";
        public string Color { get; set; } = "black";

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "div";
            output.Attributes.SetAttribute("style", $"color:{Color}");
            output.Content.SetContent($"{Prefix} {DateTime.Now:dddd}");
        }
    }
}

Здесь мы определили два свойства для tag-хэлпера — текст перед днем недели (Prefix) и цвет текста (Color). Теперь мы можем воспользоваться нашим tag-хэлпером, например, так:

<day-info>
    <day color="red" prefix="День недели:"></day>
    <day-number></day-number>
</day-info>

и получить такой вывод:

Аналогичным образом мы можем передавать в tag-хэлперы сложные объекты.  Например, изменим код хэлпера DayInfoTagHelper следующим образом

namespace AspNetMvcTagCreate.TagHelpers
{
    public class DayInfoStyle
    {
        public string Width { get; set; } = "18rem";
        public string Header { get; set; } = "День недели";

        public DayInfoStyle(string width, string header) 
        {
            Width = width;
            Header = header;
        }
    }

    public class DayInfoTagHelper : TagHelper
    {
        public DayInfoStyle? Style { get; set; }
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var childContent = await output.GetChildContentAsync();
            output.TagName = "div";
            output.Attributes.Add("class", "card");
            string content;
            

            if (string.IsNullOrEmpty(Style?.Width)==false) 
            {
                output.Attributes.Add("style", $"width: {Style.Width};");
            }
            else 
            {
                output.Attributes.Add("style", $"width: 18rem;");
            }

            if (string.IsNullOrEmpty(Style?.Header) == false)
            {
                content = $"<h5 class=\"card-title\">{Style.Header}</h5>";
            }
            else
            {
                content = $"<h5 class=\"card-title\">День недели</h5>";
            }
            output.Content.SetHtmlContent(content + childContent.GetContent());
        }
    }
}

Теперь мы можем передавать в качестве аргумента объект:

<day-info style="@(new DayInfoStyle("100%","Инфа"))">
    <day color="red" prefix="День недели:"></day>
    <day-number></day-number>
</day-info>

результат:

Итого

Управление выводом tag-хэлпера осуществляется с использованием свойств объекта TagHelperOutput. При генерации html-разметки тэга мы можем добавлять текст или другую html-разметку перед и после html-тэга хэлпера, добавлять атрибуты к html-тегу хэлпера и т.д. При необходимости, мы можем определить  классе tag-хэлпера публичные свойства, которые будут использоваться в качестве атрибутов tag-хэлпера.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии