Declined
Last Updated: 27 Aug 2020 09:17 by ADMIN

I hate to refer to this as a bug, as I'm sure there is something we are missing. Here's are the bullet points of the scenario:

  • We are using Telerik Drawer as our "NavMenu" component
  • We are using Azure AD for Authentication

In the OnLogInSucceeded section of our Authentication.razor, we are building the user specific menu from SQL tables, structuring it in a hierarchical DrawerItem list.

When I pass that back to the Data property of the TelerikDrawer, the display does not update. StateHasChanged doesn't have any impact. We have tried tying it to a "service" to listen for changes. We have even called an event that would manually make the update.


MAIN LAYOUT

@inherits LayoutComponentBase
@inject NavigationManager navigationManager
@inject PublicClient Http
@inject IMatToaster toast

@using G2_Field.Shared
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

@inject IAuthorizationService AuthorizationService
@inject Employee dbUSER

@attribute [Authorize]


    <TelerikRootComponent>
        <div>
            <NavMenu @ref="nm" items="@Data" />
        </div>

        <div class="app-main">
            <div class="app-bar">
                <div style="float:left">
                    <TelerikButton OnClick="@ToggleDrawer" Icon="@Telerik.Blazor.IconName.Menu" Class="k-flat" />
                </div>
                <div style="float:right">
                    <LoginDisplay />
                </div>
            </div>
            <div>
                @Body
            </div>
        </div>
    </TelerikRootComponent>
    <MatToastContainer />

    @code {
        public TelerikDrawer<DrawerItem> Drawer { get; set; }
        public DrawerItem SelectedItem { get; set; }
        public bool Expanded { get; set; } = true;
        NavMenu nm;

        public List<DrawerItem> Data { get; set; } =
        new List<DrawerItem>
        {
            new DrawerItem { Text = "HOME", Icon = Telerik.Blazor.IconName.Window, Description = "Home", URL="" }
        };

        public async Task ToggleDrawer() 
        {
            await nm.ToggleDrawer();
        }

        public async Task OnSidebarChange(List<DrawerItem> di)
        {
            Data = di;
            Console.WriteLine(di.Last().Children.Last().Text);
            await nm.RefreshMenu(di);
        }...

AUTHENTICATION

@page "/authentication/{Action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using G2_Field.Shared
@using System.Security.Claims
@inject Employee dbUSER
@inject PublicClient Http
@using System.Threading.Tasks

<RemoteAuthenticatorView Action="@Action" OnLogInSucceeded=@OnLogInSucceeded>
    <LoggingIn>
        You are about to be redirected to https://login.microsoftonline.com.
    </LoggingIn>
</RemoteAuthenticatorView> 

@code{
    [Parameter] public string Action { get; set; }
    AppCategories[] iMenu = new AppCategories[0];
    [CascadingParameter] private Task<AuthenticationState> authenticationStateTask { get; set; }

    [CascadingParameter] public Task<AuthenticationState> AuthenticationState { get; set; }
    [CascadingParameter] public List<DrawerItem> d { get; set; }
    [CascadingParameter(Name = "theMainLayout")] public MainLayout ml { get; set; }

    public async void OnLogInSucceeded()
    {
        var user = (await AuthenticationState).User;
        var un = (await AuthenticationState).User.Claims.ToList();
        var username = "";
        if (user.Identity.IsAuthenticated)
        {
            // Do some stuff
            Console.WriteLine("Log In Succeeded Event Fired");

            foreach (Claim u in un)
            {
                //Console.WriteLine(u.Type + " = " +  u.Value.ToString());
                if (u.Type == "preferred_username") { username = u.Value.ToString(); }
            }
            dbUSER = await Http.Client.GetJsonAsync<Employee>("/api/Index/GetCurrentEmployee/" + username);

            Console.WriteLine("EmpUserName=" + dbUSER.EmpUserName);

            var gUserName = dbUSER.EmpUserName;
            iMenu = await Http.Client.GetJsonAsync<AppCategories[]>("/api/Index/GetUserAppCategories/" + gUserName);

            d = new List<DrawerItem>();

            d.Add(new DrawerItem { Text = "HOME", Icon = "fa-home", Description = "Home", URL = "" });
            foreach (var app in iMenu)
            {
                List<DrawerItem> y = new List<DrawerItem>();
                foreach (var cat in app.ItemList)
                {
                    DrawerItem z = new DrawerItem
                    {
                        Text = cat.MenuItemTitle,
                        Icon = cat.MenuItemIcon,
                        Description = cat.MenuItemDescription,
                        URL = cat.MenuItemURL
                    };
                    y.Add(z);
                }

                DrawerItem x = new DrawerItem {
                    Text = app.MenuCategoryTitle,
                    Icon = Telerik.Blazor.IconName.Menu,
                    Description = app.MenuCategoryTitle,
                    Children = y
                };
                d.Add(x);
            }
            StateHasChanged();
            = new MainLayout();
            ml.OnSidebarChange(d);

        }
    }...



NAVMENU

@inject NavigationManager navigationManager
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using G2_Field.Shared


<TelerikDrawer @ref="@Drawer" Data="@items" MiniMode="false" Mode="@DrawerMode.Overlay" TItem="DrawerItem" SelectedItemChanged="@OnItemSelect" @bind-Expanded="@Expanded">
    <Template Context="AuthDrawerContext">
        <div class="k-drawer-items" role="menubar" aria-orientation="vertical">
            <ul>
                @foreach (var item in AuthDrawerContext)
                {
                    var selectedClass = item == SelectedItem ? "k-state-selected" : string.Empty;
                    <li @onclick="@(() => OnItemSelect(item))" class="k-drawer-item @selectedClass">
                        <div class="k-level-@(item.Level)">
                            <TelerikIcon Icon="@item.Icon"></TelerikIcon>
                            <span class="k-item-text">@item.Text</span>
                        </div>

                        @if (item.Expanded && (item.Children?.Any() ?? false))
                        {
                            <span class="k-icon k-i-arrow-chevron-down" style="position:absolute; right:0; line-height: inherit; margin: 0 8px"></span>
                        }
                        else if (!item.Expanded && (item.Children?.Any() ?? false))
                        {
                            <span class="k-icon k-i-arrow-chevron-right" style="position:absolute; right:0; line-height: inherit; margin: 0 8px"></span>
                        }
                    </li>
                }

            </ul>
        </div>
    </Template>
</TelerikDrawer>


@code {
    [Parameter] public List<DrawerItem> items { get; set; }
    public TelerikDrawer<DrawerItem> Drawer { get; set; }
    public DrawerItem SelectedItem { get; set; }
    public bool Expanded { get; set; } = true;
    public List<DrawerItem> Data { get; set; } = new List<DrawerItem> { new DrawerItem { Text = "HOME", Icon = Telerik.Blazor.IconName.Window, Description = "Home", URL = "" } };

    public async Task ToggleDrawer() => await Drawer.ToggleAsync();

    protected override void OnInitialized()
    {
        items = Data;
        SelectedItem = items.First();
        StateHasChanged();
    }

    public void OnHover()
    {

    }

    public async Task RefreshMenu(List<DrawerItem> di)
    {
        items = di;
    }