Skip to content

Blazor Sections API Proposal #46937

Closed
@surayya-MS

Description

@surayya-MS

Background and Motivation

Related to #28182.
There is a need for a feature that will allow customers to change a part of main layout depending on which page they are on. A solution to achieve that exists and was described in #28182 (comment). Similar solution was implemented as part of #10450. https://github.com/dotnet/aspnetcore/tree/main/src/Components/Components/src/Sections these classes are internal.
We want to make them a part of public API (and change a few things for other potential use cases).

Proposed API

SectionOutlet component that renders content provided by SectionContent with the same SectionId

public sealed class SectionOutlet : IComponent, IDisposable
{
    [Parameter, EditorRequired] public object SectionId { get; set; }
}
public sealed class SectionContent : IComponent, IDisposable
{
    [Parameter, EditorRequired] public object SectionId { get; set; }
    [Parameter] public RenderFragment? ChildContent { get; set; }
{

Usage Examples

Common use case would be to use SectionOutlet component in MainLayout.razor and provide the desired content via SectionContent component in other pages.
This is not the only case. You could use SectionOutlet SectionContent to modify a part of parent component depending on which child components are rendered.

Example:

  • Add this code into the default template's MainLayout.razor:
@code{
    internal static object TopbarSection = new();
}
  • Add SectionOutlet into the default template's MainLayout.razor:
<div class="top-row px-4">
    <SectionOutlet SectionId="TopbarSection" />
    <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
  • Add SectionContent into Counter.razor:
<SectionContent SectionId="MainLayout.TopbarSection">
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</SectionContent>

You'll get this:

image

If you don't want to use a static field inMainlayout.razor you could also use a string as SectionId:

<SectionOutlet SectionId="@("topbar")" />

In Counter.razor:

<SectionContent SectionId="@("topbar")">
    <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</SectionContent>

Alternative Designs

The original design with string Name as an identifier instead of object SectionId.

public sealed class SectionOutlet : IComponent, IDisposable
{
    [Parameter, EditorRequired] public string Name { get; set; }
}
public sealed class SectionContent : IComponent, IDisposable
{
    [Parameter, EditorRequired] public string Name { get; set; }
    [Parameter] public RenderFragment? ChildContent { get; set; }
{

With this design you cannot hide your SectionOutlet. This is useful when you are developing a library and you don't want any accidental content in the user's app to be rendered in library's component.

Risks

Case when SectionId is IEquatable<T> and Equals(object), GetHashCode() not overriden.

Metadata

Metadata

Assignees

Labels

api-approvedAPI was approved in API review, it can be implementedarea-blazorIncludes: Blazor, Razor ComponentsenhancementThis issue represents an ask for new feature or an enhancement to an existing one

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions