javascript - Angular Material sidenav 指令在 app.component 中不起作用
问题描述
我有一个带有 Material sidenav 的应用程序,sidenav 显示了一个带有链接的列表。其中一个链接有一个指令,如果用户权限不符合预期的权限,则隐藏它。如果我在我的标题组件中使用列表,一切正常,但在我的应用程序组件中,该指令在应用程序重新加载之前不起作用。我该如何解决?
app.component.ts
import { MatSidenav } from "@angular/material";
import { ViewChild, ViewEncapsulation, OnChanges } from "@angular/core";
import { Component, AfterViewInit, HostBinding, OnInit } from "@angular/core";
import {
Router,
NavigationStart,
NavigationEnd,
NavigationCancel
} from "@angular/router";
import { OverlayContainer } from "@angular/cdk/overlay";
import { CustomizeService } from "./services/shared-services/customize.service";
import { FocusMonitor } from "@angular/cdk/a11y";
import { SidenavService } from "./services/layout-services/sidenav.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements AfterViewInit, OnInit {
loading;
customTheme;
// theme: string;
@HostBinding("class") componentCssClass;
@ViewChild("sidenav") public sidenav: MatSidenav;
constructor(
private router: Router,
private sidenavService: SidenavService,
private focusMonitor: FocusMonitor,
public overlayContainer: OverlayContainer,
private customizeService: CustomizeService
) {
this.loading = true;
}
ngOnInit() {
this.getTheme();
this.sidenavService.setSidenav(this.sidenav);
}
ngAfterViewInit() {
this.focusMonitor.stopMonitoring(document.getElementById("clienti"));
this.router.events.subscribe(event => {
if (event instanceof NavigationStart) {
this.loading = true;
} else if (
event instanceof NavigationEnd ||
event instanceof NavigationCancel
) {
this.loading = false;
}
});
}
getTheme() {
this.customizeService.getTheme().subscribe(theme => {
this.overlayContainer.getContainerElement().classList.add(theme);
this.componentCssClass = theme || this.getLogoFromLocalStorage();
});
// this.sendTheme(theme);
}
getLogoFromLocalStorage() {
return localStorage.getItem("customStyle");
}
closeSidenav() {
this.sidenavService.close();
}
}
app.component.html
<div color="primary">
<mat-sidenav-container class="example-container" (backdropClick)="closeSidenav()">
<mat-sidenav #sidenav (keydown.escape)="closeSidenav()" disableClose>
<mat-list>
<mat-list-item (click)="closeSidenav()"><button id="clienti" mat-button [routerLink]="['/clienti']"
routerLinkActive="mat-accent">Clienti</button></mat-list-item>
<mat-list-item (click)="closeSidenav()"><button mat-button [routerLink]="['/utenti']" routerLinkActive="mat-accent">Utenti</button></mat-list-item>
<!-- <mat-list-item (click)="closeSidenav()"><butto [routerLink]="['/matricole']" routerLinkActive="mat-accent">Matricole</mat-list-item> -->
<mat-list-item (click)="closeSidenav()"><button mat-button [routerLink]="['/sks']" routerLinkActive="mat-accent">Sks</button></mat-list-item>
<mat-list-item (click)="closeSidenav()" [appCheckPermissions]="9">
<button mat-button [routerLink]="['/packs']" routerLinkActive="mat-accent">Pacchetti</button>
</mat-list-item>
<mat-list-item (click)="closeSidenav()"><button mat-button [routerLink]="['/pc']" routerLinkActive="mat-accent">Pc</button></mat-list-item>
<mat-list-item (click)="closeSidenav()"><button mat-button [routerLink]="['/rinnovi']" routerLinkActive="mat-accent">Rinnovi</button></mat-list-item>
</mat-list>
</mat-sidenav>
<mat-sidenav-content>
<app-header></app-header>
<div class="main" color="primary">
<div [hidden]="!loading" class="loader">
<app-progress-spinner></app-progress-spinner>
</div>
<div [hidden]="loading" class="router-output">
<router-outlet></router-outlet>
</div>
</div>
<app-footer></app-footer>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
检查权限.directive.ts
import { Directive, ElementRef, Renderer2, HostListener, HostBinding, Input, OnInit, TemplateRef, ViewContainerRef } from '@angular/core';
import { DataService } from '../services/shared-services/data.service';
@Directive({
selector: '[appCheckPermissions]'
})
export class CheckPermissionsDirective {
permissions: number[] = [];
constructor(
private data: DataService,
private element: ElementRef,
private renderer: Renderer2
) {
this.getPerms();
}
@Input() set appCheckPermissions(perm: number) {
if (this.permissions.includes(perm)) {
// console.log('ok');
} else {
// console.log('non autorizzato');
this.renderer.setStyle(this.element.nativeElement, 'display', 'none');
}
}
getPerms() {
this.data.getPermissionsFromToken().subscribe(permsArr => {
this.permissions = permsArr;
});
}
}
编辑permissions
:和的日志_perm
刷新前登录:
刷新后:
编辑 2
感谢 Sunil Singh 帮助我找到了问题:permissions
当我注销然后再次登录时数据不可用app.component
,需要该appCheckPermission
指令的指令不会重新初始化,因此它需要旧的权限数据,直到浏览器刷新。
解决方法是基于服务的,我不知道如何使用指令进行修复(Sunil Singh 方式不起作用)。所以我写了一个permissionService
:
permissions = [];
constructor(private data: DataService) {
this.getPerms();
}
getPerms() {
this.data.getPermissionsFromToken().subscribe(permsArr => {
this.permissions = permsArr;
});
}
isPacksManagerEnable() {
return this.permissions.includes(9);
}
该getPerms()
方法在菜单按钮单击时触发,然后在app.component
我注入服务并isPacksManagerEnable()
在模板上调用:
<mat-list-item (click)="closeSidenav()" *ngIf="permsService.isPacksManagerEnable()">
<button mat-button [routerLink]="['/packs']" routerLinkActive="mat-accent">Pacchetti</button>
</mat-list-item>
希望它可以帮助遇到我同样问题的人
解决方案
问题
您对指令有permissions
疑问appCheckPermissions
。您正在检查permissions
当时不可用的异步数据的权限。加载后,permissions
您不会触发appCheckPermissions
负责隐藏和显示链接的设置器。
使固定
它有简单的修复,您需要确保每当 有更改时permissions
,它应该触发权限检查。
修改版
检查权限.directive.ts
import { Directive, ElementRef, Renderer2, HostListener, HostBinding, Input, OnInit, TemplateRef, ViewContainerRef, AfterViewInit } from '@angular/core';
import { DataService } from '../services/shared-services/data.service';
@Directive({
selector: '[appCheckPermissions]'
})
export class CheckPermissionsDirective implements AfterViewInit {
permissions: number[] = [];
constructor(
private data: DataService,
private element: ElementRef,
private renderer: Renderer2
) {
//this.getPerms();
}
private _perm;
@Input() set appCheckPermissions(perm: number) {
this._perm = perm;
this.doPermissionCheck();
}
doPermissionCheck(){
if (this.permissions.includes(this._perm)) {
this.renderer.setStyle(this.element.nativeElement, 'display', 'block');
// console.log('ok');
} else {
// console.log('non autorizzato');
this.renderer.setStyle(this.element.nativeElement, 'display', 'none');
}
}
ngAfterViewInit() {
this.data.getPermissionsFromToken().subscribe(permsArr => {
this.permissions = permsArr;
this.doPermissionCheck();
});
}
}
注意:代码是直接编写的,
stackoverflow editor
因此可能存在拼写错误或语法错误。请自行修复。
推荐阅读
- c++ - 温纳皮。CreateWindow 中的 TrackPopupMenuEx 等效项
- javascript - 在引导程序中使元素溢出 col
- arrays - 是否可以在 Amazon Pinpoint 模板中添加对象数组作为替换值?
- gitlab-api - 如何将用户添加到受保护的分支?
- javascript - 条形超出 d3 条形图中的图表范围
- command - 在我的世界中对箭头周围的实体执行命令
- parsing - 自上而下递归解析器的语法无效
- powerbi - 如何根据在 DAX 中应用切片器的支出获得前 1 供应商名称?
- python - “从 object_detection 导入 model_lib_v2”时出现分段错误
- python - 如何通过 NestedField 中的 Django GeoShapeField 在 Elasticsearch 上保存多边形数据?