I am working with angular 12. Here is the angular html code.
<ul id="respMenu" class="horizontal-menu">
<ng-container *ngFor="let menuItem of menuItems; let i = index">
<ng-container *ngIf="IsAllowed(['admin','user'])">
<li>
<a>
<span class="title">{{menuItem.title}}</span>
</a>
</li>
</ng-container>
</ng-container>
</ul>
i am calling this method show hide my li
IsAllowed(allowedRoles){
console.log("test");
for (var i = 0; i < userRoles.length; i++) {
if(allowedRoles.includes(userRoles[i])){
return true;
}
}
}
But it console the test text like thousands of times. why is this so please suggest me better way to do it.I Have 8 menuItems its shows 8 in UI but console many times.
IsAllowed Method parameter will be loaded dynamically and will be different for every item.
As Abhishek Priyadarshi already wrote ...
The problem is the change-detection of angular. It will call your method again and again, ... to check if the value changed.
One way to solve it, is to change the change-detection. ChangeDetectionStrategy.OnPush
is the best option, but this may break your component. Please read the docs.
And here is the reason, why I wrote a new answer: You should write a new structural directive. So you can use the method on all components and have a "standard". Have a look to the strucural directive docs.
Here is a idea how your code can be look like:
<ng-container *appAllowed="user,admin">
<li>
<a>
<span class="title">{{menuItem.title}}</span>
</a>
</li>
</ng-container>
@Directive({ selector: '[appAllowed]'})
export class AllowedDirective {
constructor(private userService: UserService,
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set appAllowed(allowed: string) {
var allowedList = allowed.split(',');
for (let requiredRole of allowedList) {
if (!this.userService.hasRole(required)) {
this.viewContainer.clear();
return;
}
}
this.viewContainer.createEmbeddedView(this.templateRef);
}
}
If you can't use the ChangeDetectionStrategy.OnPush
, then you can reduce the workload, like this:
@Directive({ selector: '[appAllowed]'})
export class AllowedDirective {
private roles: string[];
constructor(userService: UserService,
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) {
userService.me().subscribe(me => this.roles = me.roles);
}
@Input() set appAllowed(allowed: string) {
var allowedList = allowed.split(',');
for (let requiredRole of allowedList) {
if (!this.roles.includes(requiredrole)) {
this.viewContainer.clear();
return;
}
}
this.viewContainer.createEmbeddedView(this.templateRef);
}
}