I have a layout (MainLayout.razor
), and it has a flag called ShowFooter
. On some pages, I want to be able to set that flag to true
, and some others to false
.
I haven't been able to find any clear instructions on how a page (i.e. a component with a route) can communicate with its layout. How could/should this be done in Blazor?
Note: You might suggest having 2 layouts, one with and one without the footer, but that wouldn't really solve my problem, I want to be able to show and hide the footer at different times on the same page. Plus, this is just one scenario where there is a need to communicate between the layout and the page. There are also countless others.
By using Blazor route parameters, you can pass values from one page to another page. Use NavigationManager to pass a value and route the parameter to another page. Follow this example to achieve passing values from one page to another.
When you call callApi in the FirstChild , it will change it's own data , if you want to change the parent's data , you need to pass a parameter to FirstChild which will be a function to call when the span is clicked and that will call the Parent 's callApi .
The simplest way to do that is to define a public Boolean property named ShowFooter in the MainLaout component, as follows:
public bool ShowFooter {get; set;}
And to cascade a reference to MainLaout component to given components, by wrapping the markup within a CascadingValue
component whose Value attribute is set to this
, like this:
@inherits LayoutComponentBase
<CascadingValue Value="this">
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="content px-4">
@Body
</div>
</div>
</CascadingValue>
@code
{
public bool ShowFooter {get; set;}
protected override void OnInitialized()
{
// Put here code that checks the value of ShowFooter and acts in
// accordance with your dear wishes
}
}
Usage in Index.razor
@code{
// Gets a reference to the MainLayout component
[CascadingParameter]
public MainLayout Layout { get; set; }
protected override void OnInitialized()
{
Layout.ShowFooter= true;
}
}
There are a few ways to do it:
The ugliest: If you have two templates you can simply select the template you want to use with the following on the top of the page/component:
@layout NoFooterLayoutName
Use cascading value in the template ( What I would recommend for your scenerio):
<CascadingValue Value="Footer"> <Child /> </CascadingValue>
Example fiddle: https://blazorfiddle.com/s/05spcuyk
And Doc: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/cascading-values-and-parameters?view=aspnetcore-5.0
In startup.cs ConfigureService method:
services.AddScoped<AppState>();
Create AppState.cs class somewhere in your project (ideally a Services folder):
public class AppState
{
public bool ShowFooter { get; set; }
public event Action StateChanged;
private void NotifyStateChanged() => StateChanged?.Invoke();
}
Then inject it in your page/components so you can change the ShowFooter Element and in your template you can create event handler (not sure if necessary) for that triggers StateHasChanged():
@inject AppState _AppState;
@implements IDisposable
.
.
.
@code{
protected override void OnInitialized()
{
_appState.StateChanged += StateChanged;
}
public void StateChanged()
{
StateHasChanged();
}
public void Dispose()
{
_appState.StateChanged -= StateChanged;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With