Create a FeatureDefinitionProvider class in Application.Contracts :
using MyApp.Localization;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Validation.StringValues;
namespace MyApp.Features
{
public class MyAppFeatureDefinitionProvider : FeatureDefinitionProvider
{
public override void Define(IFeatureDefinitionContext context)
{
var myGroup = context.AddGroup("MyApp");
myGroup.AddFeature(
"MyApp.MyFeature",
defaultValue: "false",
displayName: LocalizableString
.Create<MyAppResource>("SomeFeature"),
valueType: new ToggleStringValueType()
);
}
}
}
Enable the feature :
Refresh the page then get the feature. I expect it to be 'true' but it's always false.
First I tried in route.provider.ts
import { ConfigStateService, RoutesService, eLayoutType } from '@abp/ng.core';
import { APP_INITIALIZER } from '@angular/core';
export const APP_ROUTE_PROVIDER = [{ provide: APP_INITIALIZER, useFactory: configureRoutes, deps: [RoutesService, ConfigStateService], multi: true }];
function configureRoutes(routes: RoutesService, config: ConfigStateService) {
return () => {
routes.add([
//...
{
path: '/mymy',
name: '::Menu:MyFeature',
iconClass: 'fas fa-whatever',
order: 3,
parentName: '::Menu:MyParent',
layout: eLayoutType.application,
//requiredPolicy: 'MyApp.MyFeature', // ---> Doesn't work (I guess it only works with permissions)
//invisible: config.getFeature('MyApp.MyFeature') != 'false',// ---> Always 'false'
},
]);
};
}
Second in app.component.ts :
import { Component } from '@angular/core';
import { NavItemsService, UserMenuService } from '@abp/ng.theme.shared';
import { eThemeLeptonXComponents, eUserMenuItems } from '@volosoft/abp.ng.theme.lepton-x';
import { ConfigStateService, ReplaceableComponentsService, RoutesService } from '@abp/ng.core';
@Component({
selector: 'app-root',
template: `
<abp-loader-bar></abp-loader-bar>
<abp-dynamic-layout></abp-dynamic-layout>
<abp-gdpr-cookie-consent></abp-gdpr-cookie-consent>
`,
})
export class AppComponent {
constructor(
private replaceComponent: ReplaceableComponentsService,
private config: ConfigStateService,
private routes: RoutesService,
) {
let myFeature = this.config.getFeature('MyApp.MyFeature'); // ---> Always 'false'
if (myFeature === 'false') {
this.routes.remove(['::Menu:MyFeature']);
}
}
}
Hello,
Please try with this code
export class AppComponent implements OnInit { constructor(private replaceComponent: ReplaceableComponentsService, private config: ConfigStateService ) {} ngOnInit(): void { const currentUser = this.config.getOne("currentUser"); if(currentUser.roles.includes('admin')) { this.replaceComponent.add({ component: MySettingsComponent, key: eThemeLeptonXComponents.Settings, }); } } }
It will hide menu for 'admin' role and for other users it will show. You may customize it as per your requirement.
Thanks,
When I say other customer, I meant, another application instance but ok, I get the gist. Thanks.
However, I just realized that the removed 'settings' menu still appears in mobile :
Shouldn't it be removed as well ?
Thanks it works but what if for another customer, I want to keep the language selector (and remove the other settings) ?
How can I easily hide the bottom-right menu items ? Can I hide them separately or should I hide them one by one ?
What a coincidence, I was just looking for exactly the same feature !
The way the mobile menu currently works is confusing :
The two first menu items appear as icons on the left. When one of those items is a parent item and you click on it, its children will display.....in the full menu.
Could you please fix it so we can chose which items go left and right, and which goes in the hamburger menu ?
I was still getting the error so I tried another approach : replace the ToolbarComponent with my own, like explained here. In my custom toolbar, I can now check if the user is public or not and show the corresponding menu accordingly.
However, I get another console error :
ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'null'. Current value: 'undefined'. Expression location: MyToolbarContainerComponent component. Find more at https://angular.io/errors/NG0100
at throwErrorIfNoChangesMode (core.mjs:11010:11)
at bindingUpdated (core.mjs:14251:17)
at bindingUpdated2 (core.mjs:14266:12)
at pureFunction2Internal (core.mjs:22917:12)
at Module.ɵɵpureFunction2 (core.mjs:22711:12)
---> at MyToolbarContainerComponent_Template (toolbar-container.component.html:3:10)
at ReactiveLViewConsumer.runInContext (core.mjs:11103:13)
at executeTemplate (core.mjs:11404:22)
at refreshView (core.mjs:12898:13)
at detectChangesInView (core.mjs:13062:9)
The problem seems to be here :
<lpx-toolbar [profileRef]="profileRef$" (profileClick)="toggleCtxMenu()">
<ng-container
---> ngIf="{
user: userProfileService.user$ | async,
profileRef: profileRef$ | async
} as data"
>
<lpx-context-menu *ngIf="data.profileRef" #menu="lpx-context-menu" (lpxClickOutside)="menu.close()" [exceptedRefs]="[data.profileRef]">
<lpx-context-menu-header>
<div class="lpx-user-ctx-header">
<div class="lpx-user-ctx-img">
<lpx-avatar [avatar]="data.user?.avatar"></lpx-avatar>
</div>
<div class="lpx-user-ctx-info">
<span class="lpx-context-menu-user-name">
{{ data.user?.fullName || data.user?.userName }}
</span>
<span *ngIf="data.user?.tenant?.name as tenantName" class="lpx-context-menu-user-tenant">
{{ tenantName }}
</span>
<span class="lpx-context-menu-user-email">{{ data.user?.email }}</span>
</div>
</div>
</lpx-context-menu-header>
<ng-container *ngFor="let actions of data.user?.userActionGroups">
<lpx-context-menu-action-group>
<lpx-navbar-routes [navbarItems]="actions" [routerItem]="false"></lpx-navbar-routes>
</lpx-context-menu-action-group>
</ng-container>
</lpx-context-menu>
</ng-container>
</lpx-toolbar>
I downloaded lepton-x source code for comparison but there seems to be no difference between my html and yours.
The link you provided is for implementing passwordless authentication with MVC when I'm trying to figure out how to refresh the page without reloading (after autologin) in Angular.