Let's say most of my components have a header. I want to create a base component that has the header variable and make all the other components inherit from that component and set the header. So I have
BaseComponent
@inherits LayoutComponentBase;
<h1>@header</h1>
@Body
@code {
protected string header;
}
Component
@inherits BaseComponent;
"internal component text"
@code {
protected override void OnInitialized()
{
base.header = "Setting header for the parent"
}
}
This compiles and shows up with no errors but the base header doesn't show up. It's like anything in the base doesn't get rendered. What am I doing wrong?
P.S.
I have also tried @layout BaseComponent
, and even both directives at the same time.
As of this writing, derived razor components implement all methods of their base classes automatically, including BuildRenderTree (which renders the HTML markup that you type within the razor file). When you type nothing, that method will make no attempt at calling the base BuildRenderTree method on its own. So you need to do it manually like so:
@inherits BaseComponent;
@{
base.BuildRenderTree(__builder);
}
@code {
protected override void OnInitialized()
{
base.header = "Setting header for the parent"
}
}
Expanding on @sw1337 answer, if the derived component has no markdown you can create it as a regular cs file rather than a razor file and it will work as expected without the need to call the base BuildRenderTree method. See this github for more details.
<h1>@header</h1>
@code {
protected string header;
}
public class MyDerivedComponent : MyAbstractComponent
{
protected override void OnInitialized()
{
header = "set header from derived component";
}
}
<h1>@Header</h1>
@code {
[Parameter] public string Header { get; set; }
}
public class MyDerivedComponent : MyAbstractComponent
{
protected override void OnParametersSet()
{
// coalesce
Header ??= "Default Header from derived Component"
}
}
Some Razor File
<MyDerivedComponent></MyDerivedComponent>
Result
<h1>Default Header from derived Component</h1>
Some Razor File
<MyDerivedComponent Header="MyHeader"></MyDerivedComponent>
Result
<h1>MyHeader</h1>
Blazor Fiddle
<h3>@Header</h3>
@if (ChildContent is not null)
{
@ChildContent
}
@code {
[Parameter] public string Header { get; set; }
[Parameter] public RenderFragment ChildContent { get; set; }
}
public class MyDerivedComponent : MyBaseComponent
{
protected override void OnParametersSet()
{
// coalesce
Header ??= "Derived Component Header";
ChildContent ??= CreateDefaultChildContent();
}
private static RenderFragment CreateDefaultChildContent()
{
return builder =>
{
builder.OpenElement(0, "h4");
builder.AddContent(1, "Derived Component default child content value");
builder.CloseElement();
};
}
}
Example One
Consumer passes no parameters. Default values for Header
and ChildContent
from derived component are used.
code
<MyDerivedComponent/>
output
<h3>Derived Component Header</h3>
<h4>Derived Component default child content value</h4>
Example Two
Consumer passes Header
parameter, default ChildContent
of derived component is used.
code
<MyDerivedComponent Header="Consumer Header"/>
output
<h3>Consumer Header</h3>
<h4>Derived Component default child content value</h4>
Example Three
Consumer passes both Header
and ChildContent
parameters.
code
<MyDerivedComponent Header="Consumer Header">
<h4>Child Content - from consumer</h4>
</MyDerivedComponent>
output
<h3>Consumer Header</h3>
<h4>Child Content - from consumer</h4>
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