0

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);?

Franco
  • 441
  • 3
  • 18
  • 2
    That's what navigation IS-- loading a page, which involves resetting its variables. If you want to persist state across navigation, you need some way to SAVE that state. One way is to use a scoped service. – Bennyboy1973 Sep 29 '21 at 19:45

2 Answers2

4

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.

Guilherme
  • 5,143
  • 5
  • 39
  • 60
  • I found the problem. I forgot to declare my pages to use the layout of MainLayout so the whole app pages instead of only those pages. SO I added '@layout MainLayout' to all my pages – Franco Sep 30 '21 at 07:30
1

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:

  1. Read it from the current URL
  2. Store it as a state somewhere in the memory and read it in OnInitialized (complex and I won't really recommend)
Mayur Ekbote
  • 1,700
  • 1
  • 11
  • 14
  • I have stored it in a .cs file in a class and the subButton.StyleClassString works correctly, but the problem still remains that sometimes when I click on it dissapears. So I just don't want the component to reload or re-render. – Franco Sep 30 '21 at 07:11