I know one answer is don't use MainLayout for this one page, but I prefer to not do that as we then have to keep 2 layout pages in sync on every change in them - and that's just asking for divergence.
Here's the problem. This is my MainLayout (simplified)
<ErrorBoundary>
<ChildContent>
<main class="@pageClass">
<PopupMessageBox>
<header class="main-header">
<PrimaryNav UserAvatarUrl="@UserAvatarUrl" IsManagerOrSysAdmin="@(Principal.IsManagerOrSysAdmin())" />
</header>
<div class="main-content">
@Body
</div>
</ChildContent>
For one @Body
page we need to have <PrimaryNav>
have a slightly different menu selection. In <PrimaryNav>
we can determine what page is in @Body
, but having the page change does not cause <PrimaryNav>
to re-render.
Is there a way to force it to re-render on every page change?
@body
is the current page component. It's available in Routes
in the Router
as routeData
.
Here I'm simply cascading the Type
.
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<CascadingValue Name="PageComponent" Value="routeData.PageType">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</CascadingValue>
</Found>
</Router>
The value will be refreshed with a render cascade on each navigation.
You can then capture the cascade in NavMenu
. Here's a demo that only shows the Weather
nav link when you are on Home
.
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">BlazorApp1</a>
</div>
</div>
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
@if(_isHome)
{
<div class="nav-item px-3">
<NavLink class="nav-link" href="weather">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
</NavLink>
</div>
}
</nav>
</div>
@code {
[CascadingParameter(Name = "PageComponent")] private Type? RouteType { get; set; }
private bool _isHome => RouteType == typeof(Home);
}