Using a TagHelper
from another TagHelper
is not straightforward. This StackOverflow answer provides the basics for how to do it, but there's a ton of boilerplate.
For example, here's the answer to the original question:
var anchorTagHelper = new AnchorTagHelper
{
Action = "Home",
};
var anchorOutput = new TagHelperOutput("a", new TagHelperAttributeList(), (useCachedResult, encoder) => new HtmlString());
var anchorContext = new TagHelperContext(
new TagHelperAttributeList(new[] { new TagHelperAttribute("asp-action", new HtmlString("Home")) }),
new Dictionary<object, object>(),
Guid.NewGuid());
await anchorTagHelper.ProcessAsync(anchorContext, anchorOutput);
output.Content.SetHtmlContent(anchorOutput);
I've created a set of extension methods that reduces this friction. So instead of the above, you'd have:
var anchorTagHelper = new AnchorTagHelper
{
Action = "Home",
};
var anchorOutput = await anchorTagHelper.GetOutput("a");
output.Content.SetHtmlContent(anchorOutput);
This makes nesting a TagHelper
much more fun. Below is the extension method class:
public static class TagHelperExtensions
{
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, string tagName, string childContent)
{
return tagHelper.GetOutput(CreateContext(), tagName, childContent);
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, string tagName, params IHtmlContent[] childContent)
{
return tagHelper.GetOutput(CreateContext(), tagName, childContent);
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, string tagName)
{
return tagHelper.GetOutput(CreateContext(), tagName);
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, string tagName, Func<TagHelperContext, bool, HtmlEncoder, TagHelperContent> getChildContent)
{
var context = CreateContext();
return tagHelper.GetOutput(context, tagName, (useCachedResult, encoder) => getChildContent(context, useCachedResult, encoder));
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, string tagName, Func<TagHelperContext, bool, HtmlEncoder, Task<TagHelperContent>> getChildContent)
{
var context = CreateContext();
return tagHelper.GetOutput(context, tagName, (useCachedResult, encoder) => getChildContent(context, useCachedResult, encoder));
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, TagHelperContext context, string tagName, string childContent)
{
var content = new DefaultTagHelperContent();
content.Append(childContent);
return tagHelper.GetOutput(context, tagName, (_, __) => content);
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, TagHelperContext context, string tagName, params IHtmlContent[] childContent)
{
var content = new DefaultTagHelperContent();
foreach (var item in childContent)
content.AppendHtml(item);
return tagHelper.GetOutput(context, tagName, (_, __) => content);
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, TagHelperContext context, string tagName)
{
return tagHelper.GetOutput(context, tagName, (_, __) => new DefaultTagHelperContent());
}
public static Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, TagHelperContext context, string tagName, Func<bool, HtmlEncoder, TagHelperContent> getChildContent)
{
return tagHelper.GetOutput(context, tagName, (useCachedResult, encoder) => Task.FromResult(getChildContent(useCachedResult, encoder)));
}
public static async Task<TagHelperOutput> GetOutput(this TagHelper tagHelper, TagHelperContext context, string tagName, Func<bool, HtmlEncoder, Task<TagHelperContent>> getChildContent)
{
var textAreaOutput = new TagHelperOutput(tagName, new TagHelperAttributeList(), getChildContent);
var textAreaContext = new TagHelperContext(new TagHelperAttributeList(),
context.Items, Guid.NewGuid().ToString());
await tagHelper.ProcessAsync(textAreaContext, textAreaOutput);
return textAreaOutput;
}
private static TagHelperContext CreateContext()
{
return new TagHelperContext(new TagHelperAttributeList(), new Dictionary<object, object>(), Guid.NewGuid().ToString());
}
}