Reputation: 13
I have this use case for changing the Parent Layout Menu Item based on the razor page clicked.
For simplicity sake in the below sample Layout code i'm trying to see which child Razor page is trying to load the menu item and change the Menu item based on that.
I'm trying to avoid creating multiple layout files. If I understand it correctly Layouts only gets loaded once in the life cycle unless you refresh the browser
Please let me know if this is even possible.
@inherits LayoutComponentBase
<ul id="zMenu">
@if (RouteName.Contains("/packing_sky/"))
{
<li class='title'>Sky Packing</li>
<li><a href='/Packing_sky'>Pack</a></li>
}
else if (RouteName.Contains("/cartpick/")) {
<li class='title'>Sky Packing</li>
<li><a href='/CartPick'>Pack</a></li>
}
</div>
@code{
public String RouteName= "";
protected override void OnInitialized()
{
RouteName= "<from_razor_page>";
}
}
Thanks in advance.
Upvotes: 1
Views: 4574
Reputation: 2601
I think there are two ways to accomplish this behavior.
I will call the layout component MainLayout
.
In the first approach, the MainLayout
is responsible for "knowing" what link should be rendered. In essence, it is what you have done already. The NavigationManager
has the needed properties for the current URL. So you need to inject it.
@inject NavigationManager navManager
You are also right that the OnInitialized
method of MainLayout
will only be called once. (To be more precious, it won't be called again if the page uses the same layout). However, the NavigationManager
has an event you can subscribe to.
@code{
public String RouteName = "";
private void HandleLocationChanged(Object sender,LocationChangedEventArgs args)
{
RouteName = args.Location;
//force an update of the UI, it might be necessary in some layouts and circumstances
StateHasChanged();
}
protected override void OnInitialized()
{
RouteName = navManager.Uri;
navManager.LocationChanged += HandleLocationChanged;
}
public void Dispose()
{
navManager.LocationChanged -= HandleLocationChanged;
}
}
The call to StateHasChanged()
in the HandleLocationChanged
method ensure that the layout is updated with the new value. This might not be necessary with every layout and every circumstance. I'd recommend to test it without it, and if it doesn't work, try it with StateHasChanged()
.
I've implemented the IDisposable
interface to unsubscribe from the event. This is only beneficial if your application has multiple layouts.
The second approach would be to use a service for communication between the MainLayout
and your page component. It's like the page is "requesting" to display a link.
If you are interested in this solution, let me know, and I'll post it.
Upvotes: 5
Reputation: 13
Thank you , The approach #1 saved me a lot of code duplication. I had to make one minor change in the HandleLocactionChanged method. So I had to rebuild the HTML content again and set it via javascript as the page has got already loaded.
private void HandleLocationChanged(Object sender, LocationChangedEventArgs args)
{
RouteName = args.Location;
JSRuntime.InvokeVoidAsync(
"setHTML", new String[]{"zMenu", fetchMenuContent(RouteName)});
}
Upvotes: 0