Browse Source

Fix basic theme blazor menu remain open problem.

Resolve #21840
pull/21841/head
maliming 1 year ago
parent
commit
215b6d6433
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 39
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor
  2. 27
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs
  3. 46
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainMenuProvider.cs
  4. 43
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuItemViewModel.cs
  5. 50
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuViewModel.cs
  6. 2
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor
  7. 20
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs
  8. 36
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor
  9. 27
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor.cs

39
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor

@ -1,29 +1,29 @@
@using Volo.Abp.UI.Navigation
@{
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass;
var disabled = MenuItem.IsDisabled ? "disabled" : string.Empty;
var url = MenuItem.Url == null ? "#" : MenuItem.Url.TrimStart('/', '~');
var customComponentType = MenuItem.GetComponentTypeOrDefault();
var elementId = MenuItem.MenuItem.ElementId ?? "MenuItem_" + MenuItem.MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.MenuItem.CssClass) ? string.Empty : MenuItem.MenuItem.CssClass;
var disabled = MenuItem.MenuItem.IsDisabled ? "disabled" : string.Empty;
var url = MenuItem.MenuItem.Url == null ? "#" : MenuItem.MenuItem.Url.TrimStart('/', '~');
var customComponentType = MenuItem.MenuItem.GetComponentTypeOrDefault();
}
@if (MenuItem.IsLeaf)
@if (MenuItem.MenuItem.IsLeaf)
{
if (customComponentType != null && typeof(ComponentBase).IsAssignableFrom(customComponentType))
{
<DynamicComponent Type="@customComponentType" />
}
else if (MenuItem.Url != null)
else if (MenuItem.MenuItem.Url != null)
{
<li class="nav-item @cssClass @disabled" id="@elementId">
<a class="nav-link" href="@url" target="@MenuItem.Target">
@if (MenuItem.Icon != null)
<a class="nav-link" href="@url" target="@MenuItem.MenuItem.Target">
@if (MenuItem.MenuItem.Icon != null)
{
if (MenuItem.Icon.StartsWith("fa"))
if (MenuItem.MenuItem.Icon.StartsWith("fa"))
{
<i class="@MenuItem.Icon me-1"></i>
<i class="@MenuItem.MenuItem.Icon me-1"></i>
}
}
@MenuItem.DisplayName
@MenuItem.MenuItem.DisplayName
</a>
</li>
}
@ -38,22 +38,23 @@ else
}
else
{
<a class="nav-link dropdown-toggle" @onclick="ToggleSubMenu" id="Menu_@(MenuItem.Name)" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@if (MenuItem.Icon != null)
<a class="nav-link dropdown-toggle" @onclick="ToggleMenu" id="Menu_@(MenuItem.MenuItem.Name)"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@if (MenuItem.MenuItem.Icon != null)
{
if (MenuItem.Icon.StartsWith("fa"))
if (MenuItem.MenuItem.Icon.StartsWith("fa"))
{
<i class="@MenuItem.Icon me-1"></i>
<i class="@MenuItem.MenuItem.Icon me-1"></i>
}
}
@MenuItem.DisplayName
@MenuItem.MenuItem.DisplayName
</a>
}
<div class="dropdown-menu border-0 shadow-sm @(IsSubMenuOpen ? "show" : "")" aria-labelledby="Menu_@(MenuItem.Name)">
<div class="dropdown-menu border-0 shadow-sm @(MenuItem.IsOpen ? "show" : "")" aria-labelledby="Menu_@(MenuItem.MenuItem.Name)">
@foreach (var childMenuItem in MenuItem.Items)
{
<SecondLevelNavMenuItem MenuItem="childMenuItem" />
<SecondLevelNavMenuItem Menu="Menu" MenuItem="childMenuItem" />
}
</div>
</div>

27
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs

@ -1,37 +1,42 @@
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Volo.Abp.UI.Navigation;
using Volo.Abp.AspNetCore.Components.Web.Theming.Layout;
namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic;
public partial class FirstLevelNavMenuItem : IDisposable
{
[Inject] private NavigationManager NavigationManager { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
[Inject]
protected PageLayout PageLayout { get; set; }
[Parameter]
public ApplicationMenuItem MenuItem { get; set; }
public MenuViewModel Menu { get; set; }
public bool IsSubMenuOpen { get; set; }
[Parameter]
public MenuItemViewModel MenuItem { get; set; }
protected override void OnInitialized()
{
NavigationManager.LocationChanged += OnLocationChanged;
}
private void ToggleSubMenu()
protected virtual void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
IsSubMenuOpen = !IsSubMenuOpen;
Menu.CloseAll();
Menu.InvokeStateChanged();
}
public void Dispose()
protected virtual void ToggleMenu()
{
NavigationManager.LocationChanged -= OnLocationChanged;
Menu.ToggleOpen(MenuItem);
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
public virtual void Dispose()
{
IsSubMenuOpen = false;
InvokeAsync(StateHasChanged);
NavigationManager.LocationChanged -= OnLocationChanged;
}
}

46
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainMenuProvider.cs

@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic;
public class MainMenuProvider : IScopedDependency
{
private readonly IMenuManager _menuManager;
public MainMenuProvider(IMenuManager menuManager)
{
_menuManager = menuManager;
}
public virtual async Task<MenuViewModel> GetMenuAsync()
{
var menu = await _menuManager.GetMainMenuAsync();
var result = new MenuViewModel
{
Menu = menu,
Items = menu.Items.Select(CreateMenuItemViewModel).ToList()
};
result.SetParents();
return result;
}
private MenuItemViewModel CreateMenuItemViewModel(ApplicationMenuItem applicationMenuItem)
{
var viewModel = new MenuItemViewModel
{
MenuItem = applicationMenuItem,
};
viewModel.Items = new List<MenuItemViewModel>();
foreach (var item in applicationMenuItem.Items)
{
viewModel.Items.Add(CreateMenuItemViewModel(item));
}
return viewModel;
}
}

43
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuItemViewModel.cs

@ -0,0 +1,43 @@
using System.Collections.Generic;
using JetBrains.Annotations;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic;
public class MenuItemViewModel
{
public ApplicationMenuItem MenuItem { get; set; }
public IList<MenuItemViewModel> Items { get; set; }
public bool IsOpen { get; set; }
[CanBeNull]
public MenuItemViewModel Parent { get; set; }
public void Open()
{
Parent?.Open();
IsOpen = true;
}
public void Close()
{
foreach (var childItem in Items)
{
childItem.Close();
}
IsOpen = false;
}
public void SetParents([CanBeNull] MenuItemViewModel parent)
{
Parent = parent;
foreach (var childItem in Items)
{
childItem.SetParents(this);
}
}
}

50
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuViewModel.cs

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic;
public class MenuViewModel
{
public ApplicationMenu Menu { get; set; }
public List<MenuItemViewModel> Items { get; set; }
public EventHandler StateChanged;
public void SetParents()
{
foreach (var item in Items)
{
item.SetParents(null);
}
}
public void ToggleOpen(MenuItemViewModel menuItem)
{
if (menuItem.IsOpen)
{
menuItem.Close();
}
else
{
CloseAll();
menuItem.Open();
}
StateChanged.InvokeSafely(this);
}
public void CloseAll()
{
foreach (var item in Items)
{
item.Close();
}
}
public void InvokeStateChanged()
{
StateChanged.InvokeSafely(this);
}
}

2
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor

@ -2,6 +2,6 @@
{
foreach (var menuItem in Menu.Items)
{
<FirstLevelNavMenuItem MenuItem="menuItem" />
<FirstLevelNavMenuItem Menu="@Menu" MenuItem="@menuItem" />
}
}

20
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs

@ -11,27 +11,39 @@ namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic;
public partial class NavMenu : IDisposable
{
[Inject]
protected IMenuManager MenuManager { get; set; }
protected MainMenuProvider MainMenuProvider { get; set; }
[Inject]
protected ApplicationConfigurationChangedService ApplicationConfigurationChangedService { get; set; }
protected ApplicationMenu Menu { get; set; }
protected MenuViewModel Menu { get; set; }
protected async override Task OnInitializedAsync()
{
Menu = await MenuManager.GetMainMenuAsync();
Menu = await MainMenuProvider.GetMenuAsync();
Menu.StateChanged += Menu_StateChanged;
ApplicationConfigurationChangedService.Changed += ApplicationConfigurationChanged;
}
private void Menu_StateChanged(object sender, EventArgs e)
{
InvokeAsync(StateHasChanged);
}
private async void ApplicationConfigurationChanged()
{
Menu = await MenuManager.GetMainMenuAsync();
Menu.StateChanged -= Menu_StateChanged;
Menu = await MainMenuProvider.GetMenuAsync();
Menu.StateChanged += Menu_StateChanged;
await InvokeAsync(StateHasChanged);
}
public void Dispose()
{
if (Menu != null)
{
Menu.StateChanged -= Menu_StateChanged;
}
ApplicationConfigurationChangedService.Changed -= ApplicationConfigurationChanged;
}
}

36
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor

@ -1,26 +1,26 @@
@using Volo.Abp.UI.Navigation
@{
var elementId = MenuItem.ElementId ?? "MenuItem_" + MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.CssClass) ? string.Empty : MenuItem.CssClass;
var disabled = MenuItem.IsDisabled ? "disabled" : string.Empty;
var url = MenuItem.Url == null ? "#" : MenuItem.Url.TrimStart('/', '~');
var customComponentType = MenuItem.GetComponentTypeOrDefault();
var elementId = MenuItem.MenuItem.ElementId ?? "MenuItem_" + MenuItem.MenuItem.Name.Replace(".", "_");
var cssClass = string.IsNullOrEmpty(MenuItem.MenuItem.CssClass) ? string.Empty : MenuItem.MenuItem.CssClass;
var disabled = MenuItem.MenuItem.IsDisabled ? "disabled" : string.Empty;
var url = MenuItem.MenuItem.Url == null ? "#" : MenuItem.MenuItem.Url.TrimStart('/', '~');
var customComponentType = MenuItem.MenuItem.GetComponentTypeOrDefault();
}
@if (MenuItem.IsLeaf)
@if (MenuItem.MenuItem.IsLeaf)
{
if (customComponentType != null && typeof(ComponentBase).IsAssignableFrom(customComponentType))
{
<DynamicComponent Type="@customComponentType" />
}
else if (MenuItem.Url != null)
else if (MenuItem.MenuItem.Url != null)
{
<a class="dropdown-item @cssClass @disabled" href="@url" target="@MenuItem.Target" id="@elementId">
@if (MenuItem.Icon != null)
<a class="dropdown-item @cssClass @disabled" href="@url" target="@MenuItem.MenuItem.Target" id="@elementId">
@if (MenuItem.MenuItem.Icon != null)
{
<i class="@MenuItem.Icon me-1"></i>
<i class="@MenuItem.MenuItem.Icon me-1"></i>
}
<span>
@MenuItem.DisplayName
@MenuItem.MenuItem.DisplayName
</span>
</a>
}
@ -34,22 +34,22 @@ else
}
else
{
<a role="button" @onclick="ToggleSubMenu" class="btn dropdown-toggle" data-toggle="dropdown"
<a role="button" @onclick="ToggleMenu" class="btn dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
@if (MenuItem.Icon != null)
@if (MenuItem.MenuItem.Icon != null)
{
<i class="@MenuItem.Icon me-1"></i>
<i class="@MenuItem.MenuItem.Icon me-1"></i>
}
<span>
@MenuItem.DisplayName
@MenuItem.MenuItem.DisplayName
</span>
</a>
}
<div class="dropdown-menu border-0 shadow-sm @(IsSubMenuOpen ? "show" : "")">
<div class="dropdown-menu border-0 shadow-sm @(MenuItem.IsOpen ? "show" : "")">
@foreach (var childMenuItem in MenuItem.Items)
{
<SecondLevelNavMenuItem MenuItem="@childMenuItem"/>
<SecondLevelNavMenuItem Menu="Menu" MenuItem="childMenuItem" />
}
</div>
</div>
}
}

27
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor.cs

@ -1,37 +1,42 @@
using System;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using Volo.Abp.UI.Navigation;
using Volo.Abp.AspNetCore.Components.Web.Theming.Layout;
namespace Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic;
public partial class SecondLevelNavMenuItem : IDisposable
{
[Inject] private NavigationManager NavigationManager { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
[Inject]
protected PageLayout PageLayout { get; set; }
[Parameter]
public ApplicationMenuItem MenuItem { get; set; }
public MenuViewModel Menu { get; set; }
public bool IsSubMenuOpen { get; set; }
[Parameter]
public MenuItemViewModel MenuItem { get; set; }
protected override void OnInitialized()
{
NavigationManager.LocationChanged += OnLocationChanged;
}
private void ToggleSubMenu()
protected virtual void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
IsSubMenuOpen = !IsSubMenuOpen;
Menu.CloseAll();
Menu.InvokeStateChanged();
}
public void Dispose()
protected virtual void ToggleMenu()
{
NavigationManager.LocationChanged -= OnLocationChanged;
Menu.ToggleOpen(MenuItem);
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
public virtual void Dispose()
{
IsSubMenuOpen = false;
InvokeAsync(StateHasChanged);
NavigationManager.LocationChanged -= OnLocationChanged;
}
}

Loading…
Cancel
Save