【问题标题】:TagHelper ; how to modify dynamically added children标记助手;如何修改动态添加的孩子
【发布时间】:2017-05-26 18:56:04
【问题描述】:

asp-items Razor“TagHelper”将为SelectList 中的每个值添加一个<option><select>。我想修改每个孩子。

具体来说,我想禁用其中的一些(即添加disabled="disabled")。

更具体地说,我想动态禁用其中一些;我正在使用角度,所以我可以ng-disabled="{dynamic_boolean_which_determines_disabled}"。这意味着可以先禁用该选项,但在用户进行更改后,可以禁用该选项(无需重新加载页面)。 Angular 应该解决这个问题;我认为 Angular 和 TagHelpers 理论上应该一起工作......

我预计:

我可以以某种方式访问​​将创建的子 <option> 标签的 IEnumerable(即,SelectList 中的每个项目一个),迭代子标签,然后 SetAttribute("disabled") 或 SetAttribute("ng -禁用")...

我试过了:

  1. 创建我自己的以select[asp-items] 为目标的 TagHelper,并尝试 GetChildContentAsync() 和/或 SetContent 以达到 IEnumerable <option> 标记并迭代它们并处理每个标记,但我认为这只会让我修改整个InnerHtml 作为字符串;做一个 String.replace 感觉很糟糕,但如果这是我唯一的选择,我可以 这样做吗?即ChildrenContent.Replace("<option", "<option disabled=\"...\"")
  2. 创建我自己的 TagHelper,它以 option 元素为目标,这些元素是 select[asp-items] 的子元素,因此我可以单独处理每个元素。这有效,但不适用于由asp-items 创建的动态添加的<option>,它仅适用于我实际放入cshtml 标记中的“文字”<option> 标签。

我认为这可行,但并不理想:

  1. 如上所述,我想我可以得到 TagHelper 的动态 asp-items <option></option> <option></option> 的结果作为字符串,并进行字符串替换,但我不喜欢直接使用字符串...
  2. 我怀疑(我还没有尝试过)我可以自己做asp-items 的工作;即custom-items。但后来我通过重新做 asp-items 可以为我完成的工作来重新创建轮子?

【问题讨论】:

标签: razorengine tag-helpers


【解决方案1】:

所以我还没有阅读“AutoLinkHttpTagHelper”in the example,它使用字符串替换(特别是 RegEx 替换)来替换每个出现的 URL,<a> 指向该 URL。情况略有不同*,但是...

无论如何,一旦我学会停止担心并喜欢字符串修改,这就是我的解决方案:

[HtmlTargetElement("select", Attributes = "asp-items")]
public class AspItemsNgDisabledTagHelper : SelectTagHelper
{
    //Need it to process *after* the SelectTagHelper
    public override int Order { get; } = int.MaxValue;

    //https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/authoring#ProcessAsync
    public AspItemsNgDisabledTagHelper(IHtmlGenerator gen) : base(gen) {}

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        //Notice I'm getting the PostContent; 
        //SelectTagHelper leaves its literal content (i.e. in your CSHTML, if there is any) alone ; that's Content
        //it only **appends** new options specified; that's PostContent
        //Makes sense, but I still wasn't expecting it
        var generated_options = output.PostContent.GetContent();

        //Note you do NOT need to extend SelectTagHelper as I've done here
        //I only did it to take advantage of the asp-for property, to get its Name, so I could pass that to the angular function
        var select_for = this.For.Name;

        //The heart of the processing is a Regex.Replace, just like
        //their example https://docs.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/authoring#inspecting-and-retrieving-child-content
        var ng_disabled_generated_options = Regex.Replace(
            generated_options,
            "<option value=\"(\\w+)\">",
            $"<option value=\"$1\" ng-disabled=\"is_disabled('{select_for}', '$1')\">");

        //Finally, you Set your modified Content
        output.PostContent.SetHtmlContent(ng_disabled_generated_options);

    }

}

学习机会很少:

  1. 我以为我会找到AspForTagHelperAspItemsTagHelper,(角度背景表明相应的属性;asp-forasp-items,将是单独的“指令”,即 TagHelper)。
    1. 其实TagHelper“匹配”关注的是元素名(不像angular可以匹配元素名...属性...类...CSS选择器)
    2. 因此,我在SelectTagHelper 中找到了我要查找的内容,其中有ForItems 作为属性。有道理。
  2. 如上所述,我扩展了SelectTagHelper,但这不是必要回答我最初的问题。仅当您想像我所做的那样访问this.For.Name 时才有必要,但甚至可能有一种解决方法(即在这里重新绑定它自己的 For 属性?)
    1. 我分心了,我想我需要覆盖 SelectTagHelper 的行为来实现我的目标;即面向对象的思维。事实上,即使我确实扩展了SelectTagHelper,也不会阻止基础SelectTagHelper 的单独实例匹配和处理元素。换句话说,元素处理发生在管道中。
    2. 这解释了为什么扩展和调用 base.Process() 会导致 Select 完成其工作两次;当您的实例匹配时一次,当基础实例匹配时再一次。
    3. (我想可以通过创建像&lt;asp-items-select&gt; 这样的新元素名称来阻止SelectTagHelper 匹配?但是,没有必要......我只是避免调用base.Process()。所以除非这是一个不好的做法......)

*以这种方式不同:

  1. 他们想创建一个不存在的标签,而我想添加一个属性标签已经存在;即&lt;option&gt;
    1. 虽然&lt;option&gt;“标签”是由SelectTagHelper 在其PostContent生成(原本希望在Content 中找到它),但我不认为标签- generate-in-strings-by-content-mods 可以与它​​们对应的 TagHelper 匹配——所以也许我们真的是一样的,因为我们只是在处理普通的旧字符串
  2. 他们的“数据”又名“模型”隐含在文本本身中;他们找到一个 URL,该 URL 字符串成为他们使用的意义单位。就我而言,有一个显式的建模类; SelectList (&lt;select&gt;) 由一些 SelectListItem (&lt;option&gt;) 组成——但该课程也对我没有帮助。
    1. 那个类只给了我像public bool Disabled这样的属性(记住,这对我来说是不够的,因为disabled的值可以在浏览器中更改为true或false;即仅限客户端)和public SelectListGroup Group--当然,没有像 ng-disabled 这样不标准的东西,也没有像 Attributes 这样的“包罗万象”的属性,它可以让我在其中放置任意属性(ng-disabled 或其他任何东西)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2020-08-08
    相关资源
    最近更新 更多