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:
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;
}