diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor
index 0ccd9b93db..3b1cdc1d4d 100644
--- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor
+++ b/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))
{
}
- else if (MenuItem.Url != null)
+ else if (MenuItem.MenuItem.Url != null)
{
-
- @if (MenuItem.Icon != null)
+
+ @if (MenuItem.MenuItem.Icon != null)
{
- if (MenuItem.Icon.StartsWith("fa"))
+ if (MenuItem.MenuItem.Icon.StartsWith("fa"))
{
-
+
}
}
- @MenuItem.DisplayName
+ @MenuItem.MenuItem.DisplayName
}
@@ -38,22 +38,23 @@ else
}
else
{
-
}
-
+
@foreach (var childMenuItem in MenuItem.Items)
{
-
+
}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs
index 4cdd0ec8a4..fc1c0a2da4 100644
--- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/FirstLevelNavMenuItem.razor.cs
+++ b/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;
}
}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainMenuProvider.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MainMenuProvider.cs
new file mode 100644
index 0000000000..c8d63792d9
--- /dev/null
+++ b/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 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();
+
+ foreach (var item in applicationMenuItem.Items)
+ {
+ viewModel.Items.Add(CreateMenuItemViewModel(item));
+ }
+
+ return viewModel;
+ }
+}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuItemViewModel.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuItemViewModel.cs
new file mode 100644
index 0000000000..0c31d6dfe5
--- /dev/null
+++ b/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 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);
+ }
+ }
+}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuViewModel.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/MenuViewModel.cs
new file mode 100644
index 0000000000..28e9a19d6d
--- /dev/null
+++ b/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 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);
+ }
+}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor
index b35ec8ba2e..f0d03be25e 100644
--- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor
+++ b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor
@@ -2,6 +2,6 @@
{
foreach (var menuItem in Menu.Items)
{
-
+
}
}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs
index 5b9c07ad44..a6999173d5 100644
--- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/NavMenu.razor.cs
+++ b/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;
}
}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor
index 9200e83657..08f4f72090 100644
--- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor
+++ b/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))
{
}
- else if (MenuItem.Url != null)
+ else if (MenuItem.MenuItem.Url != null)
{
-
- @if (MenuItem.Icon != null)
+
+ @if (MenuItem.MenuItem.Icon != null)
{
-
+
}
- @MenuItem.DisplayName
+ @MenuItem.MenuItem.DisplayName
}
@@ -34,22 +34,22 @@ else
}
else
{
-
- @if (MenuItem.Icon != null)
+ @if (MenuItem.MenuItem.Icon != null)
{
-
+
}
- @MenuItem.DisplayName
+ @MenuItem.MenuItem.DisplayName
}
-
+
@foreach (var childMenuItem in MenuItem.Items)
{
-
+
}
-}
\ No newline at end of file
+}
diff --git a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor.cs b/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor.cs
index c736770884..d835082390 100644
--- a/modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/SecondLevelNavMenuItem.razor.cs
+++ b/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;
}
}