Tag Helper - 添加集合中的所有属性

Tag Helper - Add all Attributes from a Collection

我有以下标签助手(这相当于说 Html.Editor):

[HtmlTargetElement("editor", Attributes = "for", TagStructure = TagStructure.WithoutEndTag)]
public class EditorTagHelper : TagHelper {
    private readonly IHtmlHelper _htmlHelper;

    public EditorTagHelper(IHtmlHelper htmlHelper) {
        _htmlHelper = htmlHelper;
    }

    public ModelExpression For { get; set; }

    public IDictionary<string, string> HtmlAttributes { get; set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

    public string TemplateName { get; set; }

    public IDictionary<string, object> ViewData { get; set; } = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

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

    public override void Process(TagHelperContext context, TagHelperOutput output) {
        ((IViewContextAware)_htmlHelper).Contextualize(ViewContext);

        ViewData.Add("HtmlAttributes", HtmlAttributes);

        output.Content.SetHtmlContent(_htmlHelper.Editor(For.Name, TemplateName, ViewData));

        output.TagName = null;
    }
}

这样称呼:

<editor for="Name" view-data-test="@("Foo")" html-attributes-class="Bar" />

这是字符串视图模板的代码:

@model string
<input asp-for="@Model" class="form-control" />
@ViewData["Test"]
@(((IDictionary<string, string>)ViewData["HtmlAttributes"])["Class"])

这很好用,但理想情况下,我想将 HtmlAttributes 字典作为属性添加到上面的输入标签助手中。以前我会说以下将属性传递给 HTML 助手:

Html.TextBoxFor(m => m, new { htmlAttributes = ViewData["HtmlAttributes"] })

但是将它们传递给标签助手的等价物是什么?

要创建可以与您的词典一起使用的标签助手,您需要

  • 在标签助手 class 上提供一个属性,该属性采用 HTML 属性字典
  • 解构并循环遍历该字典并将其添加到输出

首先将 html-attributes 指定为 HtmlTargetElement 的逗号分隔属性列表的 HTML 属性。

[HtmlTargetElement("editor", Attributes = "for, html-attributes", TagStructure = TagStructure.WithoutEndTag)]
public class EditorTagHelper : TagHelper {

然后将它们映射到标签助手本身的 属性:

[HtmlAttributeName("html-attributes")]
public Dictionary<string, string> HtmlAttributes { get; set; }

在process方法中,通过那个字典解构和foreach

foreach (var (key, value) in HtmlAttributes)
{
    output.Attributes.SetAttribute(key, value);
}

像这样使用它:

<editor for="Name" view-data-test="@("Foo")" html-attributes="@ViewData["HtmlAttributes"]" />

编辑:

如果您只想将 ViewData 传递给模板,然后将它们应用于内部的输入元素,您需要按照我告诉您的相同过程进行操作。但是您跳过了将 htmlAttributes 应用于 Editor 元素。

    [HtmlTargetElement("input", Attributes = "for, html-attributes")]
    public class InputTagHelper : TagHelper
    {
        public ModelExpression For { get; set; }

        [HtmlAttributeName("html-attributes")]
        public Dictionary<string, string> HtmlAttributes { get; set; }

        public override void Process(TagHelperContext context,
            TagHelperOutput output)
        {
            output.TagMode = TagMode.SelfClosing;
            output.Attributes.SetAttribute("name", EditorFor.Name);
            foreach (var (key, value) in HtmlAttributes)
            {
                output.Attributes.SetAttribute(key, value);
            }
        }

然后在您的模板中,您可以:

@model string
<input asp-for="@Model" html-attributes="@((IDictionary<string, string>)ViewData["HtmlAttributes"])" />