Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

basic component layout inheritance blazor

Tags:

blazor

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.

like image 932
americanslon Avatar asked Jan 30 '20 16:01

americanslon


2 Answers

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"
    }
}
like image 51
sw1337 Avatar answered Oct 14 '22 17:10

sw1337


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.

Simple Example

Base Component (MyAbstractComponent.razor)

<h1>@header</h1>

@code {
    protected string header;
}

Derived Component

public class MyDerivedComponent : MyAbstractComponent
{
    protected override void OnInitialized()
    {
         header = "set header from derived component";
    }
}

Parameter Example

Base Component (MyAbstractComponent.razor)

<h1>@Header</h1>

@code {
  [Parameter] public string Header { get; set; }
}

Derived Component

public class MyDerivedComponent : MyAbstractComponent
{
    protected override void OnParametersSet()
    {
        // coalesce
        Header ??= "Default Header from derived Component"
    }
}

Usage 1 - Default Header From Derived Component

Some Razor File

<MyDerivedComponent></MyDerivedComponent>

Result

<h1>Default Header from derived Component</h1>

Usage 2 - Specified Header From Derived Consumer

Some Razor File

<MyDerivedComponent Header="MyHeader"></MyDerivedComponent>

Result

<h1>MyHeader</h1>

RenderFragment Parameter Example

Blazor Fiddle

MyBaseComponent.razor

<h3>@Header</h3>

@if (ChildContent is not null)
{
    @ChildContent
}

@code {
    [Parameter] public string Header { get; set; }
    [Parameter] public RenderFragment ChildContent { get; set; }
}

MyDerivedComponent.cs

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();
        };
    }
}

Usage MyRazorPage.razor

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>
like image 44
jkdba Avatar answered Oct 14 '22 17:10

jkdba