angular - Vyn uppdateras inte efter ändring i Google API callback
Jag försöker implementera en tjänst som kommer att använda Google API för att logga in användaren och auktorisera Sheets API. En förenklad version av den tjänsten:
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);
}
});
});
}
}
Jag injicerar den tjänsten i min AppComponent som private myService: MyService. I min app.component.html har jag en enkel knapp som ska vara synlig om användaren inte har godkänt API:t:
<button *ngIf="!myService.isLoggedIn">Authorize</button>Så vad jag vill är: - Tjänsten anropar gapi.auth.authorize - Om användaren har godkänt API:et, ska isLoggedIn sättas till true och knappen ska försvinna - Om omedelbar auktorisering misslyckas, ska knappen vara synlig så att användaren kan trigga auktoriseringen manuellt.
Problemet jag står inför är att när omedelbar auktorisering lyckas och "User logged in, true" skrivs ut i konsolfönstret, förblir knappen synlig. *ngIf-bindningen fungerar inte. Förändringen i isLoggedIn återspeglas inte. Jag hittade ett liknande inlägg här på SO men jag hade redan misstänkt att det kan ha att göra med återuppringningsfunktionerna, så jag hade redan försökt ändra värdet från ett setTimeout inom ett setTimeout inom ett annat setTimeout och vyn uppdateras framgångsrikt.
Jag hittade äntligen en lösning genom att injicera ChangeDetectorRef som private detector och anropa detector.detectChanges() efter att ha satt ett värde för isLoggedIn.
Så jag frågar inte efter en lösning, det jag frågar är om någon vet varför detta konstiga beteende händer och varför jag måste använda ändringsdetektorn för en operation som, åtminstone för mig, verkar vara något som borde hanteras av Angular själv. Eller missar jag något och är detta beteende normalt?
Svar #1
gapi omfattas inte av Zone.js. Du måste anropa ändringsdetektering explicit:
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
});
});
}
