Sandeep Chandan
Sandeep Chandan

Reputation: 13

How to dynamically change the Same Layout in Blazor Webassembly using an input parameter

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

Answers (2)

Just the benno
Just the benno

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

Sandeep Chandan
Sandeep Chandan

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

Related Questions