Search code examples
asp.net-corerazorblazorblazor-client-side

Blazor WASM LayoutComponentBase with @Body and more properties


My use case is I have the MainLayout.razor with this code

@inherits LayoutComponentBase
<header><nav ....></header>
<section><h1>Page Title</h1><section>
<main class="container">
    <div class="row"><div class="col-12">@Body</div></div>
</main>

Now I want to set the page title from every @Body razor fragment (maybe by inheritance)

@page "/about"
<div>....</div>
@code {
    Title = "About Title";
}

I want avoid to put <section> inside the @body fragment. Also have the same problem with the title-element from head-element. What is best practices to do this (without js interop)?


Solution

  • There are a couple of ways to do that...

    • Using CascadingValue feature Define a property in MainLayout to get the title from child components such as the about component.

      Add a CascadingValue component to MainLayout, and pass the MainLayout component as the value of the Value attribute.

      In the child component define a CascadingParameter property which stores the MainLayout object, and assign a title to its Title property

      Here's the full code:

    MainLayout

    <div class="main">
        <div class="top-row px-4 auth">
            <h1>@Title</h1>
            <LoginDisplay />
            <a href="https://learn.microsoft.com/aspnet/" target="_blank">About</a>
        </div>
    
        <div class="content px-4">
            <CascadingValue Value="this">
               @Body
            </CascadingValue>
       </div>
    
    </div>
    
    @code
    {
      string title;
    
      public string Title
     {
        get => title;
        set
        {
            if(title != value)
            { 
                title = value;
                StateHasChanged();
            }
         }
      }
    }  
    

    About.razor

    @page "/about"
    <div>....</div>
    
    @code {
        [CascadingParameter]
        public MainLayout MainLayout { get; set; }
    
        protected override void OnInitialized()
       {
    
          MainLayout.Title = "About Title";
    
       }
     }
    
    • Create a service class that defines a Title property that can be set by components into which the service is injected. This service class should also provide a way to pass the title supplied by child components to the MainLayout, which should refresh itself in order to display the provided title...

    Hope this helps...