-
Notifications
You must be signed in to change notification settings - Fork 222
Tag Helpers: Redesign of Tag Helpers content mode #221
Comments
If we have PreContent and PostContent we should also have PreTag and PostTag. With this last two we could wrap the initial tag inside other tags (based on some conditions). Imagine being able to spit out some HTML/JS for each tag but only in debug mode (or some other condition). (Of course you could go all in and have objects similar to web forms controls. My crystal ball says we would eventually have them anyway. And without the state tracking shackles it could stay simple, but powerful and useful at the same time) |
@pebezo you can do that already using the current API and this proposed change by setting |
Couldn't you use the same technique to work around not having PreContent and PostContent? I can't speak about the implementation complexity, but from a user's point of view I find the Pre/PostTag more useful than Pre/PostContent. What would be nice is if we could somehow inject code into the controls that are about to render. For example, being able to wrap a div around all tag helpers that render an |
@pebezo PreContent/PostContent is more inline with the common case for Tag Helpers while optimizing the rendering to avoid unnecessary buffering. The scenario you talk about (wrapping all |
I'm thinking |
- Removed all tests and instances of ContentBehavior in preparation for moving to a non-ContentBehavior based design. - Removed ContentBehavior specific CodeGeneration. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- Removed all tests and instances of ContentBehavior in preparation for moving to a non-ContentBehavior based design. - Removed ContentBehavior specific CodeGeneration. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- Removed all tests and instances of ContentBehavior in preparation for moving to a non-ContentBehavior based design. - Removed ContentBehavior specific CodeGeneration. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- React to aspnet/Razor#221 - Modified existing TagHelpers to no longer rely on ContentBehavior and to instead utilize GetChildContentAsync, PreContent, Content and PostContent.
- React to aspnet/Razor#221 - Modified existing TagHelper tests to no longer rely on ContentBehavior. - Updated signatures of TagHelperExecutionContext and TagHelperContext pieces.
- Removed all tests and instances of ContentBehavior in preparation for moving to a non-ContentBehavior based design. - Removed ContentBehavior specific CodeGeneration. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- React to aspnet/Razor#221 - Modified existing TagHelpers to no longer rely on ContentBehavior and to instead utilize GetChildContentAsync, PreContent, Content and PostContent.
- React to aspnet/Razor#221 - Modified existing TagHelper tests to no longer rely on ContentBehavior. - Updated signatures of TagHelperExecutionContext and TagHelperContext pieces.
- Removed all tests and instances of ContentBehavior in preparation for moving to a non-ContentBehavior based design. - Removed ContentBehavior specific CodeGeneration. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- React to aspnet/Razor#221 - Modified existing TagHelpers to no longer rely on ContentBehavior and to instead utilize GetChildContentAsync, PreContent, Content and PostContent.
- React to aspnet/Razor#221 - Modified existing TagHelper tests to no longer rely on ContentBehavior. - Updated signatures of TagHelperExecutionContext and TagHelperContext pieces.
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- Removed all tests and instances of ContentBehavior in preparation for moving to a non-ContentBehavior based design. - Removed ContentBehavior specific CodeGeneration. #221
…nt modes. - Added PreContent, PostContent and ContentSet properties to TagHelperOutput. - Added GeneratePreContent, GeneratePostContent and SupressOutput methods to TagHelperOutput. - Added multile ExecuteChildContentAsync and GetChildContentAsync to the rendering phase, ultimately only exposing GetChildContentAsync to a TagHelper author. - Added more knowledge of StartWritingScope and EndWritingScope to the TagHelper runtime components. This is to enable the runtime components to utilize the RazorPage's infrastructure to render a delegate to a writer and retrieve its value to ultimately expose it to the user. #221
- Added a new internal ctor for TagHelperExecutionContext since it's used in multiple tests to allow for less friction testing. #221
- Modified the CSharpTagHelperCodeRenderer to understand a single line of TagHelper rendering (instead of doing different things based on ContentBehavior). - Modified existing CodeGen output to reflect new content changes. #221
- React to aspnet/Razor#221 - Modified existing TagHelpers to no longer rely on ContentBehavior and to instead utilize GetChildContentAsync, PreContent, Content and PostContent.
- React to aspnet/Razor#221 - Modified existing TagHelper tests to no longer rely on ContentBehavior. - Updated signatures of TagHelperExecutionContext and TagHelperContext pieces.
- React to aspnet/Razor#221 - Modified existing TagHelpers to no longer rely on ContentBehavior and to instead utilize GetChildContentAsync, PreContent, Content and PostContent.
- React to aspnet/Razor#221 - Modified existing TagHelper tests to no longer rely on ContentBehavior. - Updated signatures of TagHelperExecutionContext and TagHelperContext pieces.
Razor commits: Mvc commits: |
This redesign unifies the various content modes of Tag Helpers and facilitates new features like conditional execution of Tag Helper contents, e.g. to support the proposed
CacheTagHelper
aspnet/Mvc#1552.ContentBehaviorAttribute
TagHelperOutput
:public string PreContent { get; set;}
: content to be rendered before child block orContent
public string PostContent { get; set;}
: content to be rendered after child block orContent
Content
property prevents the calling page from executing the child block and using its contents.public bool ContentSet { get; }
: indicates theContent
property has been explicitly set and the hosting view/page will not execute the child block and use the resulting value for the element contentpublic Task<string> GetChildBlockContentAsync()
: executes the child block and returns the resulting string valuepublic void SuppressOutput()
: sets theContent
andTagName
properties to nullThis design assumes all child blocks of Tag Helpers are emitted in delegates to support delayed execution. We could potentially introduce a new attribute
ModifyContent
that could be placed on Tag Helper classes to avoid the delegate creation except for the cases where the Tag Helper explicitly states it wants to modify content by presence of the attribute (by callingTagHelperOutput.GetChildBlockContentAsync
) if it's determined that the performance impact of always generating closure delegates is significant.The
GetChildBlockContentAsync
method should be protected from calls toFlush
andWrite
in the child block by effectively delaying requested writes and flushes until after the Tag Helper has finished being written to the output. This will avoid inadvertent flushes to the output which would potentially reorder the content from what was intended.Usage Examples
Prepending Content
Tag Helper class
Razor file
HTML output
Appending Content
Tag Helper class
Razor file
HTML output
Replacing Content
Tag Helper class
Razor file
HTML output
Modifying Content
Tag Helper class
Razor file
HTML output
Conditionally Suppressing Output
Tag Helper class
Razor file
HTML output
The text was updated successfully, but these errors were encountered: