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?
View Components in Controller Methods Rather than passing the name of your view component, you can pass its Type object, giving you some IntelliSense support, as in this example: return ViewComponent(typeof(CustomerAddressViewComponent), new { CustomerId = "A123"});
Invoke a view component directly from a controller View components are typically invoked from a view, but they can be invoked directly from a controller method. While view components don't define endpoints like controllers, a controller action that returns the content of a ViewComponentResult can be implemented.
View Components that inherit from ViewComponent class are able to call the View() method. When no specific view is called out, the view is searched in the following two ways and in the following order: Views/{ControllerName}/Components/{ComponentName}/Default. cshtml.
A View Component class can be created in the following ways. Same as Controller class, View Component class must be non-abstract, public, and non-nested. This class fully supports constructor dependency injection. It does not take part in the Controller lifecycle so that we cannot use filters in the view component.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With