用于指令变更检测的Angular2事件

时间:2016-10-05 11:27:59

标签: angular typescript angular2-directives

我有一个登录/注销的AuthService,检查用户是否已登录并使用angular2-jwt(例如使用tokenNotExpired())。

我仅为此服务创建了一个模块,以便将其用作单例。

现在我检查用户是否已登录,例如:

<p *ngIf="authService.authenticated()">Text</p>

按预期工作。

现在我想要实现的是将此*ngIf包装到自己的指令中,以便检查用户是否已登录的组件不必注入AuthService。

基本上是这样的:

<p *authenticated>Text</p>

我已经创建了这样的经过身份验证的指令:

@Directive({selector: "[authenticated]"})
export class AuthenticatedDirective {

    constructor(private templateRef: TemplateRef<any>,
                private viewContainer: ViewContainerRef,
                private auth: AuthService) {
    }

    @Input() set authenticated(condition: boolean) {
        if (this.auth.authenticated()) {
            console.log("IsLoggedIn");
            this.viewContainer.createEmbeddedView(this.templateRef);
        } else {
            console.log("NotLoggedIn");
            this.viewContainer.clear();
        }
    }

}

它基本上是* ngIf指令,只是它没有使用参数。

问题是,只有在加载网站时才会调用它,它不会定期检查this.auth.authenticated()以查看令牌是否已过期。

如果指令没有收听,那么触发变更检测当然不会做任何事情,因此手动触发(例如,在注销后)它无法正常工作。

我知道你可以&#34;听&#34; (使用host或HostListeners)指令中的事件,但是我无法找到更改检测的事件,我可以使用该事件触发指令以更新&#34;。

所以基本上我的问题是,我怎样才能听取更改检测事件,还是有更好的解决方案来包装这个*ngIf="authService.authenticated()"

提前致谢。

更新:

根据@Chrillewoodz的评论,我终于想起了生命周期钩子,特别是提到的DoCheck。

我目前的指令解决方案是:

@Directive({selector: "[authenticated]"})
export class AuthenticatedDirective implements DoCheck {

    private isAuthenticated = false;

    constructor(private templateRef: TemplateRef<any>,
                private viewContainer: ViewContainerRef,
                private auth: AuthService) {
    }


    ngDoCheck() {
        if (this.isAuthenticated !== this.auth.authenticated()) {
            this.isAuthenticated = this.auth.authenticated();
            if (this.auth.authenticated()) {
                console.log("IsLoggedIn");
                this.viewContainer.createEmbeddedView(this.templateRef);
            } else {
                console.log("NotLoggedIn");
                this.viewContainer.clear();
            }
        }
    }

}

1 个答案:

答案 0 :(得分:4)

我认为编写指令的方式需要使用像

这样的指令
<p *authenticated="isAuthenticated">Text</p>

isAuthenticated返回truefalse的位置(无论您是否经过身份验证)

我认为您应该向authService.authenticated()添加一个可通知的观察点,而不是轮询authService

@Directive({selector: "[authenticated]"})
export class AuthenticatedDirective {

    constructor(private templateRef: TemplateRef<any>,
                private viewContainer: ViewContainerRef,
                private auth: AuthService) {
        auth.isAuthenticated.subscribe(authenticated => {
          if (authenticated()) {
              console.log("IsLoggedIn");
              this.viewContainer.createEmbeddedView(this.templateRef);
          } else {
              console.log("NotLoggedIn");
              this.viewContainer.clear();
          }
        });
    }
}

https://angular.io/docs/ts/latest/cookbook/component-communication.html显示了一些关于如何使用observable创建服务的很好的例子。