Given some parent / child TagHelper(s).
Parent
[HtmlTargetElement("div", Attributes = "parent-context")]
public class AspFormViewTagHelper : TagHelper
{
[HtmlAttributeName("parent-context")]
public string? Prefix { get; set; }
public override void Init(TagHelperContext context)
{
context.Items["parent-context"] = Prefix;
}
}
Child
[HtmlTargetElement("input", Attributes = "asp-for, child-context")]
public class AspForVueTagHelper : TagHelper
{
[HtmlAttributeName("asp-for")] public ModelExpression For { get; set; }
[HtmlAttributeName("child-context")] public String ChildContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!context.Items.ContainsKey("parent-context"))
return;
var prefix = (string) context.Items["parent-context"];
// The above is null when using an editor template?
}
}
When rendering HTML, this works perfectly.
<div id="person" role="tabpanel" aria-labelledby="home-tab" parent-context="parent">
<div >
<div >
<input asp-for="@Model.Person.FirstName" child-context="child" />
</div>
</div>
</div>
However, if I render an Editor Template, then the context is lost.
<div id="person" role="tabpanel" aria-labelledby="home-tab" parent-context="parent">
@Html.EditorFor(_ => _.Person.FirstName, "boot-text-child")
</div>
With boot-text-child.cshtml
containing this....
<div >
<div >
<input asp-for="@Model" child-context="from-editor-template" />
</div>
</div>
The parent context is gone.
Why does the heirarchy of rendering break down when an editor template is used. Is there any way to force the rendering so that the context is maintained for an Editor Template.
The child is correctly called both times, but when the editor template is used, the context.Items
is empty.
CodePudding user response:
The issue might relates the scope of TagHelperContext, I checked your code on my side and set some break point in the custom tag and relate view page, it seems that when using the following code:
<div id="person" role="tabpanel" aria-labelledby="home-tab" parent-context="parent">
<div >
<div >
<input asp-for="@Model.Person.FirstName" child-context="child" />
</div>
</div>
</div>
The break point order is: Main page => AspFormViewTagHelperc.cs => AspForVueTagHelper.cs
But if using Editor Template and @Html.EditorFor
, the order is: Main page => AspFormViewTagHelperc.cs => Editor Template page => AspForVueTagHelper.cs.
If I put the parent
div into the Editor Template page, the context.Items
contains the value. The Editor Template page code like this:
<div id="person" role="tabpanel" aria-labelledby="home-tab" parent-context="parent">
<div >
<div >
<input asp-for="@Model" child-context="child" />
</div>
</div>
</div>
In the main page, only using the Html.EditorFor
, like this:
@Html.EditorFor(_ => _.Person.FirstName, "boot-text-child")
So, you can use this method to render the elements or directly using the tag helper instead of using @Html.EditorFor
.