I'm writing a custom TagHelper and want to render a ViewComponent inside it. Something similar to what vc:xyz tag helper does, but in a more controlled way, so that I can determine at runtime which ViewComponent to render.
Is it possible?
I'm writing a custom TagHelper and want to render a ViewComponent inside it. Something similar to what vc:xyz tag helper does, but in a more controlled way, so that I can determine at runtime which ViewComponent to render.
Is it possible?
In order to do that, you need to inject IViewComponentHelper into your TagHelper, contextualize it and then use it to render any ViewComponent depending on your application logic. Here is a quick illustration:
[HtmlTargetElement("widget", Attributes = WidgetNameAttributeName)]
public class WidgetTagHelper : TagHelper
{
private const string WidgetNameAttributeName = "name";
private readonly IViewComponentHelper _viewComponentHelper;
public WidgetTagHelper(IViewComponentHelper viewComponentHelper)
{
_viewComponentHelper = viewComponentHelper;
}
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
[HtmlAttributeName(WidgetNameAttributeName)]
public string Name { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
((IViewContextAware)_viewComponentHelper).Contextualize(ViewContext);
var content = await _viewComponentHelper.InvokeAsync(typeof(WidgetViewComponent), new { name = Name });
output.Content.SetHtmlContent(content);
}
}
Also, keep in mind that self-closing tags will NOT work:
<widget name="abc" />
Use this form instead:
<widget name="abc"></widget>
A follow up on the answer.
There is no need to write end tag when calling the tag helper. Just set the TagMode in ProcessAsync:
output.TagMode = TagMode.StartTagAndEndTag;
output.Content.SetHtmlContent(content);
Then <widget name="abc" />
works perfectly fine.
Alternatively, you can render the content of the view component in place of the widget
tag without rendering the tag itself:
output.SuppressOutput();
output.PostElement.SetHtmlContent(content);
I also noticed that adding self-closing tags in the view component's view makes them appear wrong in the final result, but that may be a different topic.
© 2022 - 2024 — McMap. All rights reserved.