Right now it's not possible to have a template component and use it along with ChildContent. For example if I have i component:
MyTemplatedComponent.cshtml
<div class="class1">
<div class="class2">something here</div>
@ChildContent
<div class="class3">
@Feedback
</div>
</div>
@functions{
[Parameter] protected RenderFragment ChildContent { get; set; }
[Parameter] protected RenderFragment Feedback { get; set; }
}
Wanted usage:
<MyTemplatedComponent>
This should be a component default content!!
<Feedback>
Hello from feedback!
</Feedback>
<MyTemplatedComponent>
The problem is that I cannot use it like in the previous example because I get an error:
Unrecognized child content inside component 'MyTemplatedComponent'. The component 'MyTemplatedComponent' accepts child content through the following top-level items: 'ChildContent', 'Feedback'.
Current usage:
If I specifiy ChildContent explicitly it works
<MyTemplatedComponent>
<ChildContent>
This should be a component default content!!
</ChildContent>
<Feedback>
Hello from feedback!
</Feedback>
<MyTemplatedComponent>
I think that template parameters should behave as a placeholder and be used when specified. Also ChildContent content should be used implicitly in all cases. If it's not specified it should be a default content for a component.
Thanks for contacting us, @stsrki.
Your proposal would eliminate the possibility of having a content, which contains other components.
Hence, the current working mechanism of specifying each content explicitly is the intended way to do this.
/cc @danroth27
FWIW, I agree with OP that the proposed syntax should be supported. I also do not understand the comment by @mkArtakMSFT - what is the possibility being eliminated here?
In my case I have this component:
@if (Template != null)
{
@Template(ChildContent)
}
else
{
<h4 class="card-title">@ChildContent</h4>
}
@functions {
[Parameter]
RenderFragment ChildContent { get; set; }
[Parameter]
RenderFragment<RenderFragment> Template { get; set; }
}
I can now use this component like this (without a template):
<CardTitle>This is the card title</CardTitle>
I can also do this for a more complex title:
<CardTitle><img src="..." /> This is the card title</CardTitle>
However, when specifying a template, I suddenly need to do this:
<CardTitle>
<Template>
<h2 class="card-title">@context</h2>
<Template>
<ChildContent>
<img src="..." /> This is the card title
</ChildContent>
</CardTitle>
This is bad! I don't see why the content in ChildContent could not automatically be pulled into that RenderFragment if it is found without a containing block. I.e.:
<CardTitle>
<Template>
<h2 class="card-title">@context</h2>
<Template>
<img src="..." /> This is the card title
</CardTitle>
And here's an additional thought. If you insist on using top-level containing blocks for this use case, it is still bad that the block now MUST be named ChildContent. If I have to use top-level blocks, I would rather call this block Content or something else altogether - but if I do that, the block needs to be specified at all times, even when no templates are included.
I believe you should reconsider your design in this area. The current system does not allow for the most convenient public-facing (i.e. component user) APIs to be constructed - or at least it makes it quite a burden on the component developer to add support for various common structural variations.
Most helpful comment
FWIW, I agree with OP that the proposed syntax should be supported. I also do not understand the comment by @mkArtakMSFT - what is the possibility being eliminated here?
In my case I have this component:
I can now use this component like this (without a template):
I can also do this for a more complex title:
However, when specifying a template, I suddenly need to do this:
This is bad! I don't see why the content in
ChildContentcould not automatically be pulled into thatRenderFragmentif it is found without a containing block. I.e.:And here's an additional thought. If you insist on using top-level containing blocks for this use case, it is still bad that the block now MUST be named
ChildContent. If I have to use top-level blocks, I would rather call this blockContentor something else altogether - but if I do that, the block needs to be specified at all times, even when no templates are included.I believe you should reconsider your design in this area. The current system does not allow for the most convenient public-facing (i.e. component user) APIs to be constructed - or at least it makes it quite a burden on the component developer to add support for various common structural variations.