简体   繁体   中英

Angular2 Event for Change detection for Directive

I have an AuthService which logs in/out, checks if the user is logged and works with angular2-jwt (for example uses tokenNotExpired() ).

I created a Module only for this service to use it as a singleton.

Now I check if the user is logged in for example with this:

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

Which works as expected.

Now what I want to achieve is to wrap this *ngIf into a own directive so that the components checking if the user is logged in, don't have to inject the AuthService.

Basically like this:

<p *authenticated>Text</p>

I have created the authenticated directive like this:

@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();
        }
    }

}

It is basically the *ngIf directive, only that it doesn't use the parameter.

The problem is that it only gets called when the site is loaded, it doesn't check this.auth.authenticated() regularly to see if the token is expired.

Triggering the change detection of course doesn't do anything if the directive doesn't listen for it, so manually triggering (for example, after a logout) it doesn't work.

I know that you can "listen" (with host or HostListeners) for events in the directive, but I can't find the event for the change detection, with which I could trigger the directive to "update".

So basically my question is, how can I listen to the change detection event or is there a better solution for wrapping this *ngIf="authService.authenticated()" ?

Thanks in advance.

UPDATE:

With the comment from @Chrillewoodz I finally remembered lifecycle hooks, especially the mentioned DoCheck.

My current solution for the directive is now this:

@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();
            }
        }
    }

}

I think the way your directive is written you would need use your directive like

<p *authenticated="isAuthenticated">Text</p>

Where isAuthenticated returns true or false (whether or not your are authenticated)

I think instead of polling authService.authenticated() you should add an observable to authService that notifies about.

@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 shows some nice examples about how to create services with observables.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM