[Blazor] component inheritance, rendering logic in base component

See original GitHub issue

I would like to propose a very simple inheritance improvement with Blazor components:

Simply put: If you would inherit from a base .razor component and you haven’t specified any content in the inherited .razor component, do not override the BuildRenderTree method.

Why? I have created .razor components decorated with the abstract keyword in the partial class. The rendering logic (layout) is located in the base .razor component; this gives me the benefit of re-usage. If I inherit from this base component, BuildRenderTree is method is always overriden, even if I haven’t specified any content. I can work around this, but its unnecessary redundant.


How is it working now?

BaseComponent.razor

@code 
{
    [Parameter]
    public string Value { get; set; }
}
The current value is: @Value

InheritNoContent.razor

@inherits BaseComponent

InheritNoContentBaseRender.razor

@inherits BaseComponent
@{ 
    base.BuildRenderTree(__builder);
}

If I use the above sample in a Razor file:

<BaseComponent Value="Sample_1" />
<InheritNoContent Value="Sample_2" />
<InheritNoContentBaseRender Value="Sample_3" />

the output would be:

The current value is: Sample_1
(empty)
The current value is: Sample_3

The above pattern is working, however it’s quite redundant to create 2 razor components for every implementation of BaseComponent. I’m also calling base.BuildRenderTree(__builder); myself, this feels a bit hacky and possible unsupported/not recommended.


My proposal:

If you would inherit from a base .razor component and you haven’t specified any content, do not generate the override BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder), or, as an alternative, call the base implementation.


Sample: BaseComponent.razor

@code 
{
    [Parameter]
    public string Value { get; set; }
}
The current value is: @Value

InheritNoContent.razor

@inherits BaseComponent

If I use the above sample in a Razor file:

<BaseComponent Value="Sample_1" />
<InheritNoContent Value="Sample_2" />

the output would be:

The current value is: Sample_1
The current value is: Sample_2

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:27
  • Comments:16 (7 by maintainers)

github_iconTop GitHub Comments

5reactions
JvanderStadcommented, May 13, 2020

I was thinking a little bit more about this; maybe the inherit mechanism can be even better:

If by convention you would inherit from a base component which has a ChildContent-parameter defined

[Parameter]
public RenderFragment ChildContent { get; set; }

‘Inject’ the Razor content of the inherited component into the ChildContent of the inherited-component. The generated code would be something like this:

protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
	__builder.OpenComponent<BaseComponent>(0);
	__builder.AddAttribute(1, "ChildContent", (RenderFragment)( (builder2) => {

		//  Code generation for the inherited component

	} ));

	__builder.CloseComponent();
}

alternatively

Set the value of ChildContent to the Razor content of the inherited component and call the base renderer.

ChildContent = @"generated code from this component";

protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
    base.BuildRenderTree(__builder);
}

This would shortcut the need to define parent/child content by simply inheriting from another component

Possible related: #7268

3reactions
ChristopherHawscommented, Sep 28, 2022

@mkArtakMSFT I dont feel like this approach meets the standards set by a lot of the other parts of the framework, specifically people using the framework should be able to fall into the “pit of success”. At the very least it seems like there could be a method on the base type which doesnt take the __builder protected field. Even something as simple as base.Render() would be better IMO.

As for the breaking change, you could still call base.BuildRenderTree(__builder) if you wanted to do so. Maybe an analyzer could be created to recommend base.Render()? I just don’t feel like the current approach is very discoverable and definitely feels like a hack.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Blazor - Base Render in an inherited component doesn't ...
I'm trying to make a Blazor component that I will then specialize and override some methods. ... ZoomCampaign is then called from another...
Read more >
ASP.NET Core Razor components
The Blazor framework processes a component internally as a render tree, which is the combination of a component's DOM and Cascading Style Sheet ......
Read more >
ASP.NET Core Razor component rendering
By default, Razor components inherit from the ComponentBase base class, which contains logic to trigger rerendering at the following times:.
Read more >
Can you use inheritance on blazor components?
Yes. Look at MudBlazor component library on GitHub. Their components use inheritance and base classes for their components.
Read more >
Extend and Customize the Syncfusion Components in Blazor
The Syncfusion Blazor components can extend and customize the logic by creating a new Blazor component. ... Inherit any Syncfusion Blazor component and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found