Search code examples
bindblazor

How to use @bind-PropertyName withing @Body


I have a project with many pages. The structure is: Parent page that includes Menu, header, and context. The task is to send some string from the context page to the header. The question is: how do I use @bind-PropertyName on @Body?

MainLayout.razor:

@inherits LayoutComponentBase

<div class="sidebar">
    <NavMenu />
</div>

<div class="main">

    <div class="top-row px-4">
        <Header PageTitle="@_PageTitle" />
    </div>
        <div class="content px-4">
            @Body
        </div>
</div>
@code{
    private string _PageTitle { get; set; }
}

Header component:

<div>Title: @PageTitle</div>
@code {
    [Parameter]
    public string PageTitle { get; set; }
}

Context component:

@page "/plainpage"
<div> @PageTitle </div>

<Content />

@code{
    [Parameter]
    public string PageTitle { get; set; } = "Plain Page";

    public EventCallback<string> Initialized { get; set; }

    protected override void OnInitialized()
    {
        OnPageInitialized(); 
    }

    private Task OnPageInitialized()
    {
        return Initialized.InvokeAsync(PageTitle);
    }
}

If instead of @Body I had <PlainPage /> component, I would do <PlainPage @bind-PageTitle="_PageTitle" />. But how do I do it with @Body?


Solution

  • The easiest way is to use a CascadingValue which the "context" pages can use to call back to the layout.

    So, in your MainLayout, wrap @Body in a CascadingValue

    <div class="content px-4">
      <CascadingValue Value=@this>
      @Body
      </CascadingValue>
    </div>
    

    In the @code of your MainLayout create a public method

    public void SomeMethod(string SomeString)
    {
      // Do Something With SomeString like setting PageTitle
    }
    

    And in the code of your "context" use a CascadingParameter

    [CascadingParameter] MainLayout mainLayout {get;set;}
    
    protected override void OnInitialized()
    {
      mainLayout.SomeMethod(PageTitle);
    }