2016-11-28 12 views
2

Google APIを使用してユーザーをログインさせ、Sheets APIを承認するサービスを実装しようとしています。そのサービスの簡略化されたバージョン:Google APIコールバックの変更後に更新が反映されないビュー

import {Injectable} from '@angular/core'; 

declare var gapi; 

@Injectable() 
export class MyService{ 
    isLoggedIn: boolean = false; 
    clientId: string = "*******.apps.googleusercontent.com"; 
    scopes: string[] = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]; 


    constructor(){ 
     gapi.load('client',() => { 
      console.log("Client Loaded"); 
      gapi.auth.authorize({ 
       client_id: this.clientId, 
       scope: this.scopes.join(' '), 
       immediate: true 
      }, (authResponse) => { 
       if(authResponse && !authResponse.error){ 
        this.isLoggedIn = true; 
        console.log("User logged in, " + this.isLoggedIn); 
       } 
       else{ 
        this.isLoggedIn = false; 
        console.log("User not logged in"); 
        console.log(this.isLoggedIn); 
       } 
      }); 
     }); 
    } 
} 

私はprivate myService: MyServiceとして私AppComponentにそのサービスを注入しています。私のapp.component.htmlでは、私は、ユーザーがAPIを承認していない場合に表示されている必要があり、簡単なボタンがあります。

<button *ngIf="!myService.isLoggedIn">Authorize</button>

それでは、私がしたいことは次のとおりです。 - サービスはgapi.auth.authorize を呼び出す - ユーザーが許可している場合APIの場合isLoggedIntrueに設定され、ボタンは消えます。 - 即時認証が失敗した場合は、ユーザーが手動で認証を開始できるようにボタンが表示されている必要があります。

直面している問題は、直ちに承認が成功し、「ユーザーがログインしたとき、true」がコンソールウィンドウに表示され、ボタンが表示されたままになるという問題です。 *ngIfバインドが機能しません。 isLoggedInの変更は反映されません。私は同様のポストhere in SOを見つけましたが、私は既にそれがコールバックと関係があるかもしれないと疑っていましたので、setTimeoutからsetTimeout内の値を別のsetTimeoutに変更しようとしました。

最後にChangeDetectorRefprivate detectorとして注入し、isLoggedInの値を設定した後にdetector.detectChanges()を呼び出して解決策を見つけました。

私は解決策を求めているわけではありません。なぜこの奇妙な動作が起こるのか誰かが知っているのですが、なぜ少なくとも私にとっては変化検出器を使用する必要があるのでしょうか? Angular自身が扱うべきもの。それとも、私は何かを逃していますが、この動作は正常ですか?

答えて

1

gapiはZone.jsの対象外です。

constructor(private cdRef:ChangeDetectorRef){ 
    gapi.load('client',() => { 
     console.log("Client Loaded"); 
     gapi.auth.authorize({ 
      client_id: this.clientId, 
      scope: this.scopes.join(' '), 
      immediate: true 
     }, (authResponse) => { 
      if(authResponse && !authResponse.error){ 
       this.isLoggedIn = true; 
       console.log("User logged in, " + this.isLoggedIn); 
      } 
      else{ 
       this.isLoggedIn = false; 
       console.log("User not logged in"); 
       console.log(this.isLoggedIn); 
      } 
      cdRef.detectChanges(); // <<<< added 
     }); 
    }); 
} 
+0

これはまさに私がやったことであり、それはうまくいきました。だから、これはZoneの仕組みと関係がありますか? – dimlucas

+0

NgZoneは非同期APIコールを認識していないため、Angular外のgapiを初期化するためだと思います。また、Angular内で初期化して、ゾーンに気づかずにイベントを処理することも可能です。 NgZoneはすべての可能性の100%をカバーしていません。 –

関連する問題