在ASP.NET Core MVC中嵌套TagHelpers [英] Nesting TagHelpers in ASP.NET Core MVC

查看:96
本文介绍了在ASP.NET Core MVC中嵌套TagHelpers的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ASP.NET Core TagHelper文档给出以下示例:

public class WebsiteContext
{
    public Version Version { get; set; }
    public int CopyrightYear { get; set; }
    public bool Approved { get; set; }
    public int TagsToShow { get; set; }
}

[TargetElement("website-information")]
public class WebsiteInformationTagHelper : TagHelper
{
    public WebsiteContext Info { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "section";
        output.Content.SetContent(
            $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
            <li><strong>Copyright Year:</strong> {Info.CopyrightYear}</li>
            <li><strong>Approved:</strong> {Info.Approved}</li>
            <li><strong>Number of tags to show:</strong> {Info.TagsToShow}</li></ul>");
        output.TagMode = TagMode.StartTagAndEndTag;
    }
}

然后可以在Razor .cshtml中使用它,如下所示:

<website-information info="new WebsiteContext {
    Version = new Version(1, 3),
    CopyrightYear = 1790,
    Approved = true,
    TagsToShow = 131 }"/>

这将生成以下HTML:

<section>
    <ul>
        <li><strong>Version:</strong> 1.3</li>
        <li><strong>Copyright Year:</strong> 1790</li>
        <li><strong>Approved:</strong> true</li>
        <li><strong>Number of tags to show:</strong> 131 </li>
    </ul>
</section>

这是非常丑陋的标记帮助程序语法.是否有某种方法可以嵌套另一个标记帮助程序并获得完整的智能感知,以便网站信息唯一允许的子级可以是上下文?请参见下面的示例:

<website-information>
    <context version="1.3" copyright="1790" approved tags-to-show="131"/>
</website-information>

在我的用例中,website-information元素已经具有许多属性,我想添加一个或更多个单独的嵌套元素.

更新

我在ASP.NET GitHub页面上提出了建议,以实现此功能用于TagHelpers.

解决方案

您当然可以嵌套标签帮助程序,尽管其他选项(例如视图组件,局部视图或显示模板)可能更适合OP所描述的场景./p>

这可能是一个非常简单的 child 标记助手:

[HtmlTargetElement("child-tag", ParentTag="parent-tag")]
public class ChildTagHelper : TagHelper
{
    public string Message { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        // Create parent div
        output.TagName = "span";
        output.Content.SetContent(Message);
        output.TagMode = TagMode.StartTagAndEndTag;     
    }
}

这也可能是另一个简单的父级标签帮助程序:

[HtmlTargetElement("parent-tag")]
[RestrictChildren("child-tag")]
public class ParentTagHelper: TagHelper
{
    public string Title { get; set; }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {            
        output.TagName = "div";

        // Add some specific parent helper html
        var header = new TagBuilder("h1");
        header.Attributes.Add("class", "parent-title");
        header.InnerHtml.Append(this.Title);
        output.PreContent.SetContent(header);

        // Set the inner contents of this helper(Will process any nested tag helpers or any other piece of razor code)
        output.Content.SetContent(await output.GetChildContentAsync());            
    }
}

然后在剃须刀视图中可以编写以下内容:

<parent-tag title="My Title">
    <child-tag message="This is the nested tag helper" />
</parent-tag>

将被呈现为:

<div>
    <h1 class="parent-title">My Title</h1>
    <span>This is the nested tag helper</span>
</div>

您可以可选地强制将标签帮助程序以特定方式嵌套:

  • 在父标记助手中使用[RestrictChildren("child-tag", "another-tag")]来限制允许的嵌套标记助手
  • 在声明子标签助手时使用ParentTag参数来强制将标签嵌套在特定的父标签[HtmlTargetElement("child-tag", ParentTag = "parent-tag")]

The ASP.NET Core TagHelper documentation gives the following example:

public class WebsiteContext
{
    public Version Version { get; set; }
    public int CopyrightYear { get; set; }
    public bool Approved { get; set; }
    public int TagsToShow { get; set; }
}

[TargetElement("website-information")]
public class WebsiteInformationTagHelper : TagHelper
{
    public WebsiteContext Info { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "section";
        output.Content.SetContent(
            $@"<ul><li><strong>Version:</strong> {Info.Version}</li>
            <li><strong>Copyright Year:</strong> {Info.CopyrightYear}</li>
            <li><strong>Approved:</strong> {Info.Approved}</li>
            <li><strong>Number of tags to show:</strong> {Info.TagsToShow}</li></ul>");
        output.TagMode = TagMode.StartTagAndEndTag;
    }
}

This can then be used in your Razor .cshtml as follows:

<website-information info="new WebsiteContext {
    Version = new Version(1, 3),
    CopyrightYear = 1790,
    Approved = true,
    TagsToShow = 131 }"/>

This will generate the following HTML:

<section>
    <ul>
        <li><strong>Version:</strong> 1.3</li>
        <li><strong>Copyright Year:</strong> 1790</li>
        <li><strong>Approved:</strong> true</li>
        <li><strong>Number of tags to show:</strong> 131 </li>
    </ul>
</section>

This is pretty ugly tag helper syntax. Is there some way to nest another tag helper and get full intelli-sense so that the only allowed child of website-information can be context? See example below:

<website-information>
    <context version="1.3" copyright="1790" approved tags-to-show="131"/>
</website-information>

In my use case, the website-information element already has many attributes and I want to add one or more separate nested elements.

UPDATE

I have raised this suggestion on the ASP.NET GitHub page to implement this feature for TagHelpers.

解决方案

You can certainly nest tag helpers, although maybe other options like view components, partial views or display templates might be better suited for the scenario described by the OP.

This could be a very simple child tag helper:

[HtmlTargetElement("child-tag", ParentTag="parent-tag")]
public class ChildTagHelper : TagHelper
{
    public string Message { get; set; }

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        // Create parent div
        output.TagName = "span";
        output.Content.SetContent(Message);
        output.TagMode = TagMode.StartTagAndEndTag;     
    }
}

And this could also be another simple parent tag helper:

[HtmlTargetElement("parent-tag")]
[RestrictChildren("child-tag")]
public class ParentTagHelper: TagHelper
{
    public string Title { get; set; }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {            
        output.TagName = "div";

        // Add some specific parent helper html
        var header = new TagBuilder("h1");
        header.Attributes.Add("class", "parent-title");
        header.InnerHtml.Append(this.Title);
        output.PreContent.SetContent(header);

        // Set the inner contents of this helper(Will process any nested tag helpers or any other piece of razor code)
        output.Content.SetContent(await output.GetChildContentAsync());            
    }
}

In a razor view you could then write the following:

<parent-tag title="My Title">
    <child-tag message="This is the nested tag helper" />
</parent-tag>

Which would be rendered as:

<div>
    <h1 class="parent-title">My Title</h1>
    <span>This is the nested tag helper</span>
</div>

You can optionally enforce tag helpers to be nested in a particular way:

  • Use [RestrictChildren("child-tag", "another-tag")] in the parent tag helper to limit the allowed nested tag helpers
  • Use the ParentTag parameter when declaring the child tag helper to enforce the tag being nested inside a particular parent tag [HtmlTargetElement("child-tag", ParentTag = "parent-tag")]

这篇关于在ASP.NET Core MVC中嵌套TagHelpers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆