2016-10-05 6 views
2

私はログイン/ログアウトするAuthServiceを持っており、ユーザがログに記録されていて、angular2-jwt(例えば、tokenNotExpired()を使用)で動作しているかどうかを確認します。指令の変更検出のためのAngular2イベント

私はこのサービスのためだけにシングルトンとしてモジュールを作成しました。期待どおりに動作

<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()を定期的にチェックしてトークンが期限切れになっていないかどうかを確認することです。

ディレクティブがリッスンしていない場合、コースの変更検出をトリガーすることは何もしないので、手動でトリガーする(ログアウト後など)、動作しません。

私は、ディレクティブ内のイベントに対して(ホストまたはHostListenersを使用して) "リッスン"できることを知っていますが、変更検出のイベントを見つけることができません。

基本的に私の質問は、変更検出イベントを聞くにはどうすればいいですか、これをラッピングするためのより良い解決法がありますか?*ngIf="authService.authenticated()"

ありがとうございます。

UPDATE:私は最終的にライフサイクルフックを思い出し@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

おそらく、あなたの解決策は 'DoCheck'でしょう。 – Chrillewoodz

+0

ありがとう、ライフサイクルのフックについて考えなかった.... それはもちろん動作します。 – derpawe

答えて

4

私はあなたの指示が書かれている方法は、あなたが

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

isAuthenticated戻りtrueまたはfalse(のようなあなたのディレクティブを使用し必要だと思います

私はポーリングの代わりにと思っていますあなたが通知する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には、オブザーバブルでサービスを作成する方法の良い例がいくつか示されています。

+0

(もう一度)素早い答えをありがとう。私の質問のコメントのDoCheckは今のところ働いています。 この場合、私はすでにobservables/subscriptionsで作業しようとしましたが、私の場合はうまくいきませんでした。おそらく私は何か間違っていましたが、角度が本当に指示が変更されていないと思います。 サブスクリプションはDoCheckフックを使用するよりも優れたソリューションと思いますか? – derpawe

+0

間違いなく。 'ngDoCheck'は数百回または数千回呼び出すことができます。これは、アプリケーションのライフサイクル中に通常10回未満変化するものに対しては、これが非常に非効率的であると想像することができます。値が変わるまで観測可能なものは何も呼び出されません。 –

+1

もちろん、「放送」は小切手をポーリングするよりも安価です。私は午前の被験者と宇宙飛行士/ミッションのアプローチを試みましたが(私の頭部からは)、視界を更新しませんでした。私は明日また試してみて、ここでコメントしたり、うまくいけば私の質問を編集したりします。 – derpawe

関連する問題