Hi,
Ok, I've implemented the changes in your last commit and that has resolved the issue I'm having with the stylesheets loading multiple times as well as the user menu not being clickable. I appreciate your help in resolving this issue.
Curious though if with abp9+ there is a better way of implementing custom layouts on a page by page basis while utilizing all the underlying leptonx components, etc. We have purchased the full source code and I see abp developer comments indicating that there should be a better way of doing this in the future.
Thanks again.
checking it now, but any resolution to the js function that does not exist in 7.3.0-rc.3?
Hi,
You have not address the issue with the stylesheets loading multiple times as stated in bullet point #1 in my previous response. Additionally when I apply these fixes to my actual project which is based on ABP 7.3.0-rc.3 I get the following error when my blazor app launches.
Hi,
So the sample has been updated completely now it Git to show you the problems I'm having.
Thanks.
I've updated the solution in git for you
Hi,
For starters change the .RequiredPermissions on sample1, sample2 and sample3 in the menu contribution to host
context.Menu.AddItem(
new ApplicationMenuItem(
"Sample1",
"Sample1",
"/Sample1",
icon: "fa fa-chart-line",
order: 3
).RequirePermissions(ABPSamplePermissions.Dashboard.Host)
);
context.Menu.AddItem(
new ApplicationMenuItem(
"Sample2",
"Sample2",
"/Sample2",
icon: "fa fa-chart-line",
order: 4
).RequirePermissions(ABPSamplePermissions.Dashboard.Host)
);
context.Menu.AddItem(
new ApplicationMenuItem(
"Sample3",
"Sample3",
"/Sample3",
icon: "fa fa-chart-line",
order: 5
).RequirePermissions(ABPSamplePermissions.Dashboard.Host)
);
and then start gong to them. you'll see the css stylesheet files bein loaded several times.
Any update?
Hi,
I have created a private repo on github for you to view, however currently it's not working/running as typically a generated solution using abp tools does not work without coding changes. I have made my specific changes to demostrate the issue but can't really go any further with it until you tell me why I can run this solution that was produced by abp studio.
You should have received an invite to the repo.
Any update on this?
I had previously created a ticket on loading a pages layout dynamically which is now working for me, however when set the layout to the default 'SideMenuLayout' the user menu in the upper right does not seem to be able to be clicked on. I have experimented with overriding the OnAferRenderAsync of the SideMenuLayout class and when invoke 'initleptonX' and 'AfterLeptonXInitialization' functions every time that seems to fix the click issue, but then it causes the stylesheets to load multiple times.
I have 3 different layouts that I switch between (see DynamicLayoutPicker.razor.cs), so I have the same OnAfterRenderAsync method on my other two layouts defined the same way I have the SideMenuLayout.cs
Any idea how I can resolve this?
DynamicLayoutPicker.razor
@inherits LayoutComponentBase
<LayoutView Layout="@CurrentLayout">
@Body
</LayoutView>
DynamicLayoutPicker.razor.cs
using CFDataSystems.StructureCloud.Blazor.Themes.LeptonX.Layouts.TenantLayout;
using CFDataSystems.StructureCloud.Components.Layouts;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;
using System.Threading.Tasks;
using System;
using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout;
namespace CFDataSystems.StructureCloud.Blazor.Themes.LeptonX.Layouts;
public partial class DynamicLayoutPicker : LayoutComponentBase, IDisposable
{
[Inject] private NavigationManager _navManager { get; set; }
public Type CurrentLayout { get; set; } = typeof(SideMenuLayout);
protected override Task OnInitializedAsync()
{
_navManager.LocationChanged += OnLocationChanged;
SetLayout(_navManager.Uri);
return base.OnInitializedAsync();
}
public void Dispose()
{
_navManager.LocationChanged -= OnLocationChanged;
}
private void OnLocationChanged(object sender, LocationChangedEventArgs e)
{
SetLayout(e.Location);
}
private void SetLayout(string location)
{
if (location.Contains("tenant-procedure-list"))
{
CurrentLayout = typeof(ProceduresPageLayout);
}
else if (location.Contains("SampleTenantDefault"))
{
CurrentLayout = typeof(TenantDefaultLayout);
}
else
{
CurrentLayout = typeof(SideMenuLayout);
}
StateHasChanged();
}
}
ToolbarContributor.cs
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using System;
using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme;
using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars;
using SideMenuUserMenu = Volo.Abp.AspNetCore.Components.WebAssembly.LeptonXTheme.Components.ApplicationLayout.SideMenu.MainHeader.MainHeaderToolbarUserMenu;
using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout;
using CFDataSystems.StructureCloud.Blazor.Themes.LeptonX.Layouts;
namespace CFDataSystems.StructureCloud.Blazor.Toolbars;
public class StructureToolbarContributor : IToolbarContributor
{
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
{
if (context.Toolbar.Name == StandardToolbars.Main)
{
var options = context.ServiceProvider.GetRequiredService<IOptions<LeptonXThemeBlazorOptions>>().Value;
if (options.Layout == typeof(DynamicLayoutPicker))
{
context.Toolbar.Items.Add(new ToolbarItem(typeof(SideMenuUserMenu)));
}
}
return Task.CompletedTask;
}
}
Abp Module Setting Toolbar options
Configure<AbpToolbarOptions>(options =>
{
//Add the standard toolbar contributors as we are using the leptonX theme
options.Contributors.Add(new LeptonXThemeToolbarContributor());
//Add our own toolbar contributor as we are using the DynamicLayoutPicker component to dynamically change the layout
//based on specific changes and we need to explicitly add the TopMenuUserMenu component to the toolbar.items collection since
//the base LeptonX theme toolbar contributor does not factor in out custom layout.
var layoutOptions = context.Services.GetRequiredService<IOptions<LeptonXThemeBlazorOptions>>().Value;
if (layoutOptions.Layout == typeof(DynamicLayoutPicker))
{
options.Contributors.Add(new StructureToolbarContributor());
}
//This is going to be used to receiving the messages coming from cobol to fire off popup's etc coming from
//the Acu2Web pages
//options.Contributors.Add(new MessageToolBarContributor());
});
private void ConfigureTheme()
{
Configure<LeptonXThemeBlazorOptions>(options =>
{
//options.Layout = LeptonXBlazorLayouts.SideMenu;
options.Layout = typeof(DynamicLayoutPicker);
});
//https://abp.io/docs/latest/ui-themes/lepton-x/blazor?UI=Blazor#customization
Configure<LeptonXThemeOptions>(options =>
{
options.Styles.Add("structurecloud",
new LeptonXThemeStyle(
LocalizableString.Create<StructureCloudResource>("Theme:StructueCloud"),
"bi bi-circle-fill"));
options.Styles.Remove(LeptonXStyleNames.System);
options.Styles.Remove(LeptonXStyleNames.Light);
options.Styles.Remove(LeptonXStyleNames.Dark);
options.Styles.Remove(LeptonXStyleNames.Dim);
options.DefaultStyle = "structurecloud";
});
}
SideMenuLayoutOverride.cs (I seem to have to do this to prevent the css stylesheets from loading muliple times)
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Options;
using Microsoft.JSInterop;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.AspNetCore.Components.Web.LeptonXTheme.Components.ApplicationLayout;
using Volo.Abp.DependencyInjection;
using Volo.Abp.LeptonX.Shared;
namespace CFDataSystems.StructureCloud.Blazor.Themes.LeptonX.Layouts.TenantLayout;
[ExposeServices(typeof(SideMenuLayout))]
[Dependency(ReplaceServices = true)]
public partial class SideMenuLayoutOverride : SideMenuLayout
{
[Inject]
IJSRuntime JSRuntime { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
var bExists = await UtilsService.HasClassOnTagAsync("body", "lpx-theme-" + Options.Value.DefaultStyle);
if (!bExists)
{
await UtilsService.AddClassToTagAsync("body", GetBodyClassName());
await JSRuntime.InvokeVoidAsync("initLeptonX", new[] { "side-menu", Options.Value.DefaultStyle });
await JSRuntime.InvokeVoidAsync("afterLeptonXInitialization", new[] { "side-menu", Options.Value.DefaultStyle });
}
}
private string GetBodyClassName()
{
return "lpx-theme-" + Options.Value.DefaultStyle;
}
}