我创建了一个angular 4指令,以便根据用户的权限显示部分视图。 加载应用程序时会触发指令,但在登录或注销后不会调用它们,这会导致视图保持不变,用户权限已更改。真的会提供一些帮助。
@Directive({
selector: '[accessLevel]'
})
export class AccessLevelDirective {
private levelToPredicateMapper: {[id: string] : () => Observable<boolean>} = {};
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef,
private readonly credantialsStorage: CredantialsStorageService,
private readonly authentication: AuthenticationService) {
this.createAccessLevelToPredicatesMapper();
}
@Input() set accessLevel(level: string) {
if (level == null) {
return;
}
let hasAccessLevelFunc = this.levelToPredicateMapper[level];
if (hasAccessLevelFunc == null) {
this.viewContainer.clear();
return;
}
hasAccessLevelFunc().subscribe(hasAccessLevel => {
this.buildOrDestroyView(hasAccessLevel);
})
}
@Input() set roles(roles: [string]) {
this.authentication.isAuthenticated()
.subscribe(isAuthenticated => {
let isValidArrayWithRoles = roles != null && Array.isArray(roles) && roles.length > 0;
let isUserHasOneOfTheRoles = isAuthenticated &&
this.credantialsStorage.get() &&
isValidArrayWithRoles &&
some(this.credantialsStorage.get().roles , role => roles.indexOf(role) > -1);
this.buildOrDestroyView(isUserHasOneOfTheRoles);
})
}
private buildOrDestroyView(isAuthorized: boolean) {
if (isAuthorized) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
private createAccessLevelToPredicatesMapper() {
this.levelToPredicateMapper['all'] = () => Observable.of(true);
this.levelToPredicateMapper['guest'] = () => this.authentication.isAuthenticated().map(isAuth => !isAuth);
this.levelToPredicateMapper['authenticated'] = () => this.authentication.isAuthenticated()
}
}
&#13;
<div id="navbar-menu" class="collapse navbar-collapse float-xs-none" [ngbCollapse]="menuHidden">
<div class="navbar-nav">
<a class="nav-item nav-link text-uppercase" routerLink="/login" routerLinkActive="active" *accessLevel="'guest'">
<i class="fa fa-home"></i>
<span translate>Login</span>
</a>
<a class="nav-item nav-link text-uppercase" routerLink="/registration" routerLinkActive="active" *accessLevel="'guest'">
<i class="fa fa-home"></i>
<span translate>Register</span>
</a>
<a class="nav-item nav-link text-uppercase" routerLink="/home" routerLinkActive="active">
<i class="fa fa-home"></i>
<span translate>Home</span>
</a>
<a class="nav-item nav-link text-uppercase" routerLink="/about" routerLinkActive="active">
<i class="fa fa-question-circle"></i>
<span translate>About</span>
</a>
<a class="nav-item nav-link text-uppercase" routerLink="/order/new" routerLinkActive="active">
<i class="fa fa-question-circle"></i>
<span translate>Create Order</span>
</a>
<a class="nav-item nav-link text-uppercase" routerLink="/orders" routerLinkActive="active" *accessLevel="'authenticated'">
<i class="fa fa-question-circle"></i>
<span translate>My Orders</span>
</a>
<ng-template accessLevel [roles]="['admin']">
<a class="nav-item nav-link text-uppercase" routerLink="/admin" routerLinkActive="active">
<i class="fa fa-question-circle"></i>
<span translate>Admin</span>
</a>
</ng-template>
</div>
&#13;
答案 0 :(得分:1)
我无法看到你的指令应该如何&#34;重新评估&#34;在您登录后
首先,最好描述re-evaluation
。
但一般情况下:
除非你的指令知道状态(登录或不登录),否则它不会对外界做出反应。
有很多方法可以让它发挥作用:
1-通过@Inputs
:
你可以拥有一个@Input set state
,状态是否可以登录,并根据你可以做出的反应(运行你喜欢的任何功能)
2-使用路由器状态:
您可以将Router
注入您的指令并订阅它的更改,当路线更改为/login
时,您可以运行您的功能(您的重新评估)
3-通过共享的observable:
你可以创建一个Subject
并在你的组件和你的指令之间共享它,并让指令订阅,并且组件将触发一个事件,并根据该运行你的重新评估。