【问题标题】:View not updating after change in Google API callbackGoogle API 回调更改后视图未更新
【发布时间】:2016-11-28 09:43:03
【问题描述】:

我正在尝试实施一项服务,该服务将使用 Google API 让用户登录并授权 Sheets 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,则 isLoggedIn 应设置为 true 并且按钮应消失 - 如果立即授权失败,按钮应该是可见的,以便用户可以手动触发授权。

我面临的问题是,当立即授权成功并且在控制台窗口中打印“用户登录,真实”时,按钮保持可见。 *ngIf 绑定不起作用。 isLoggedIn 中的更改未反映。我发现了一个类似的帖子here in SO,但我已经怀疑它可能与回调有关,所以我已经尝试在另一个setTimeout 中更改setTimeout 中的值setTimeout 并且视图成功更新.

我终于找到了解决方案,将ChangeDetectorRef 注入为private detector 并在为isLoggedIn 设置值后调用detector.detectChanges()

所以我不是要寻求解决方案,我要问的是是否有人知道为什么会发生这种奇怪的行为,以及为什么我必须使用更改检测器进行至少对我来说似乎有点像的操作这应该由 Angular 自己处理。还是我遗漏了什么而这种行为是正常的?

【问题讨论】:

    标签: angular typescript google-api google-sheets-api


    【解决方案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
            });
        });
    }
    

    【讨论】:

    • 是的,这正是我所做的,并且奏效了。所以这一切都与 Zone 的运作方式有关?
    • 我猜这是因为你在 Angular 之外初始化了 gapi,因此 NgZone 不知道它的异步 API 调用。如果您在 Angular 中对其进行初始化,它也有可能以某种方式处理事件而没有区域通知。 NgZone 并未涵盖 100% 的所有可能性。
    猜你喜欢
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 1970-01-01
    相关资源
    最近更新 更多