I am building a dynamic Drop Down Navigation bar in Blazor. Now the problem is that when paging occurs the Navbar component reloads and the drop down dissapears (which is not what I want).
I know this is true because when I take the navigationManager.NavigateTo(route);
out of the equation then it works as intended.
My MainLayout:
<div style="height: 100%; width: 100%; display: flex;">
<div style="height: 100%; width: 170px">
<NavigationMenu></NavigationMenu>
</div>
<div class="flex-child-expand">
@Body
</div>
</div>
NavigationMenu.razor
<div>
@foreach (var navButton in NavManager.MainNavButtons)
{
<div class="dropdown">
<button class="@navButton.StyleClassString" @onclick="@(() => OnButtonClicked(navButton, navButton.ButtonRoute))">@navButton.ButtonString</button>
<div class="dropdown-content">
@foreach (var button in navButton.SubSection)
{
<button class="@button.StyleClassString" @onclick="@(() => OnButtonClicked(navButton, button.ButtonRoute, button.ButtonString))">@button.ButtonString</button>
}
</div>
</div>
}
</div>
private void OnButtonClicked(NavManager.NavButton mainButtonPressed, string route, string buttonString = "")
{
if(buttonString == "")
{
foreach (var mainbtn in NavManager.MainNavButtons)
{
if (mainbtn.Section == mainButtonPressed.Section)
{
mainbtn.StyleClassString = ButtonActiveStyle.active;
}
else
{
mainbtn.StyleClassString = ButtonActiveStyle.normal;
}
//cleanup
foreach (var subButton in mainbtn.SubSection)
{
subButton.StyleClassString = ButtonActiveStyle.normal;
}
}
if(mainButtonPressed.SubSection.Count > 0)
{
mainButtonPressed.SubSection[0].StyleClassString = ButtonActiveStyle.active;
}
}
else
{
foreach (var mainbtn in NavManager.MainNavButtons)
{
if (mainbtn.Section == mainButtonPressed.Section)
{
mainbtn.StyleClassString = ButtonActiveStyle.active;
}
else
{
mainbtn.StyleClassString = ButtonActiveStyle.normal;
}
foreach (var subButton in mainbtn.SubSection)
{
if (subButton.ButtonString == buttonString)
{
subButton.StyleClassString = ButtonActiveStyle.active;
}
else
{
subButton.StyleClassString = ButtonActiveStyle.normal;
}
}
}
}
GoToPage(route);
}
private void GoToPage(string route)
{
navigationManager.NavigateTo(route);
}
*Sorry for bad indentation.
So is there a way to make the NavigationMenu.razor component from not rendering or reloading it's state when I call navigationManager.NavigateTo(route);
?
CodePudding user response:
To avoid a component to auto reload, you should override the ShouldRender
method, and make it always return false.
However, you should check your resulting HTML. It seems that the page that you are navigating into does not inherit MainLayout.
This means that it will overwrite the
<div style="height: 100%; width: 100%; display: flex;">
<div style="height: 100%; width: 170px">
<NavigationMenu></NavigationMenu>
</div>
<div class="flex-child-expand">
@Body
</div>
</div>
portion for whatever the page contains, even if you return false in the ShouldRender.
A state change in the NavigationMenu component should not make it disappear.
CodePudding user response:
NavigateTo(route) loads an entire page afresh specified by the 'route' address. Layouts are specified at a page level. When you navigate to an address, the layout is initialized again and its UI state is reset. This means that all your dropdown expansions, formatting changes etc are lost. For example, in your case, the following CSS assignment is lost:
subButton.StyleClassString = ButtonActiveStyle.normal;
StyleClassString members of subButton(s) will be reset to the initial value (is it null?)
Therefore, the only way you can make sure that the dropdown persists its state, is if you store it somewhere. You can achieve it in two ways:
- Read it from the current URL
- Store it as a state somewhere in the memory and read it in OnInitialized (complex and I won't really recommend)