Search code examples
blazorstaterendering.net-8.0

Blazor Web App - changing navmenu options based on details when user logs in


I have a Blazor Web App - .net 8. I log in the user using Microsoft Entra. The user is then added to our own database and has to be linked to an account. If they are linked, the NavMenu should show them more options. When the user logs in, the details for the user are then read in from our database. I can't get the NavMenu to see that something has changed. Or to tell the NavMenu to rerender. I was looking at this project - https://blazorhelpwebsite.com/ViewBlogPost/28 and setup a dummy project but its not working either. The counter doesn't display on the menu.

So this is the "CounterState" class

public class CounterState
{
    // _currentCount holds the current counter value
    // for the entire application
    private int _currentCount = 0;
    // StateChanged is an event handler other pages
    // can subscribe to 
    public event EventHandler StateChanged;
    // This method will always return the current count
    public int GetCurrentCount()
    {
        return _currentCount;
    }
    // This method will be called to update the current count
    public void SetCurrentCount(int paramCount)
    {
        _currentCount = paramCount;
        StateHasChanged();
    }
    // This method will allow us to reset the current count
    public void ResetCurrentCount()
    {
        _currentCount = 0;
        StateHasChanged();
    }
    private void StateHasChanged()
    {
        // This will update any subscribers
        // that the counter state has changed
        // so they can update themselves
        // and show the current counter value
        StateChanged?.Invoke(this, EventArgs.Empty);
    }
}

then registered it in Program.cs

builder.Services.AddScoped<CounterState>();

NavMenu is

@using BlazorWebApp.SessionState
@inject CounterState CounterState
 

@implements IDisposable

<div class="top-row ps-3 navbar navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="">BlazorWebApp</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>
                <p style="color:white">Counter State: @CounterState.GetCurrentCount()</p>
            </div>
        </div>

        <AuthorizeView>
         @*    <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> *@

            <div class="nav-item px-3">
                <NavLink class="nav-link" href="unauthenticate">
                    <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Unauthenticated
                </NavLink>
            </div>

            <div class="nav-item px-3">
                <NavLink class="nav-link" href="authenticate">
                    <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Authenticated
                </NavLink>
            </div>

            <div class="nav-item px-3">
                <NavLink class="nav-link" href="userdetails">
                    <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User Details
                </NavLink>
            </div>


        </AuthorizeView>
    </nav>
</div>

@code {

    // This method is called when the control is initialized
    protected override void OnInitialized()
    {
        // Subscribe to the StateChanged EventHandler
        CounterState.StateChanged +=
        OnCounterStateAdvancedStateChanged;
    }
    // This method is fired when the CounterState object
    // invokes its StateHasChanged() method
    // This will cause this control to invoke its own
    // StateHasChanged() method refreshing the page
    // and displaying the updated counter value
    void OnCounterStateAdvancedStateChanged(
        object sender, EventArgs e) => StateHasChanged();

    void IDisposable.Dispose()
    {
        // When this control is disposed of
        // unsubscribe from the StateChanged EventHandler
        CounterState.StateChanged -=
        OnCounterStateAdvancedStateChanged;
    }
}

And the counter page is

@page "/counter"
@rendermode InteractiveServer
@using BlazorWebApp.SessionState
@inject CounterState CounterState
 

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @CounterState.GetCurrentCount()</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

<!-- Add a button to reset the current count -->
<!-- that calls the CounterState class directly -->
<button class="btn btn-primary"
        @onclick="CounterState.ResetCurrentCount">
    Reset Count
</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        // Call the GetCurrentCount() method
        // to get the current count
        int CurrentCount = CounterState.GetCurrentCount();
        // Increase the count
        CurrentCount++;
        // Set Current count on the Session State object
        CounterState.SetCurrentCount(CurrentCount);
    }
}

 

The counter page works but the counter on the navmenu remains zero. Any ideas what is wrong - I'm assuming some change since 2019 but I can't find any suggestions.

Or any other ideas to do what I want to do.

Thanks


Solution

  • I found the solution this morning. In the NavMenu componenent - add in the line

    @rendermode InteractiveServer