outline
Rendering a tag helper inside another tag helper
UPDATE: The content of the following post has been revisited with improvements in a more recent post check it out.
Lately, I was prototyping around the idea of creating asp.net core tag helper that will basically behave like the angular 2’s dynamic form. The idea is to have a tag helper that generates automatically a form from a C# model class in order to avoid coding the form cshtml
by hand which can be sometimes tedious and repetitive.
During my fiddling I came across the need to render a tag helper inside the Process
method of another tag helper.
In this post I wanted to share what I discovered so far, we are going to see a very striped down example of how to implement the aforementioned behavior. The full code for the example is available on Github.
The Example
In the previous screenshot the inner html p
element having a red border is rendered from the InnerTagHelper
, the outer html div having a black border is rendered from the WrapperTagHelper
.
The WrapperTagHelper
renders the InnerTagHelper
programmatically inside its Process
method. The following snippet shows how the WrapperTagHelper
is used:
We can see here that we did not use the InnerTagHelper
, yet it gets displayed.
InnerTagHelper
As we can see in the previous code the InnerTagHelper.Process
method just sets the output html tag to be a p
element, sets a class attribute for styling purposes and finally fills the content of the paragraph with the "This is from the inner tag helper"
phrase.
Now let’s take a look at the WrapperTagHelper
.
Rendering the InnerTagHelper
In order to render a TagHelper
we need:
- an instance of the
TagHelper
that we wish to render - an instance of the
TagHelperContext
class - an instance of the
TagHelperOutput
class
The TagHelper.Process
method is then called and the result can be accessed in the TagHelperOutput
instance.
Consider the following snippet from the WrapperTagHelper
’s code:
The WrapperTagHelper.Process
method uses the private renderInnerTagHelper
to get the content generated by the InnerTagHelper
, let’s dissect this method.
First the InnerTagHelper
class is instantiated, then in order to call the InnerTagHelper.Process
we need to create a TagHelperOutput
instance; this is done in the next statement.
The constructor for TagHelperOutput
needs the following arguments:
tagName
which represents the output html tag name, in our case this is set insideInnerTagHelper.Process
that is why we just pass an empty string.attributes
represents the list ofTagHelperAttribute
s, this list contains the html - attributes accessible fromoutput.Attributes
, we just pass an empty list in our example since we don’t need to pass initial attributes toInnerTagHelper
getChildContentAsync
is a lambda expression that is supposed to asynchronously return the content of the renderedTagHelper
, in our example we just pass a lambda expression that returns an emptyTagHelperContent
object sinceInnerTagHelper
does not have child content.
Then we call the InnerTagHelper.Process
method with the context
and output
argument. Note that in our example, we used the TagHelperContext
passed to WrapperTagHelper.Process
by the asp.net core machinery.
Finally, after calling Process
output
will be populated with the generated content. All we have to do now is to generate the actual Html tag before returning it.
Closing Thoughts
After a little a bit of experimentation, I still have some interrogations worth considering:
-
Is it OK to use the
context
instance? Or should a new instance be created? perhaps a copy? -
How to create a
getChildContentAsync
lambda in order to generate child content?
I will of course share the answers as soon as I get the interrogations figured out :-)