【问题标题】:Angular 2 component global variable is undefined?Angular 2 组件全局变量未定义?
【发布时间】:2016-06-24 15:54:52
【问题描述】:

我试图在模板中创建一个 if 语句,以在数组长度为

我就是这样尝试的:

<div *ngIf="socialNetworks.length > 1">
  <div class="alert-box warning radius">You can still connect some accounts</div>
  <button class="btn btn-primary" *ngFor="let network of socialNetworks" (click)="loginSocialNetwork(network)">
             {{network.title}}
  </button>
</div>

但我总是收到一个错误,说它无法读取未定义的属性长度。

我在 Angular 2 组件中定义了变量 socialNetworks[]:

export class MyAccountComponent implements OnInit {
  socialNetworks: socialNetwork[];
  campaigns: Campaign[];
  showGreeting: boolean = true;

constructor(
    private _dataservice: DataService) {
}

然后,在一个单独的方法中,我在此处从金字塔视图的响应中设置值:

getSocialNetworks() {
    var url: string;
    url = "/account_api"
    this._dataservice.getDataByUrl(url)
      .subscribe(
        res => this.socialNetworks = res,
        err => this.logError(err)
      )
  }

即使我在此处的末尾添加一个 console.log 语句来查看 this.socialNetworks 的值,它也会说它是未定义的。但是在调试器中我可以看到 this.socialNetworks 的值不是未定义的。

所以我的问题是,我只是错误地引用了全局变量,还是我错过/误解了一些东西?

【问题讨论】:

    标签: debugging typescript angular global-variables


    【解决方案1】:

    在我看来,socialNetworks 在构造时未设置为空数组,因此在初始化时将未定义。尝试将 top socialNetwork 更改为:

    socialNetworks: socialNetwork[] = [];
    

    我们在下面的 cmets 中谈到的问题很可能与 subscribe 方法中的 this 有关。它将其分配给不正确的范围。 试试下面:

    getSocialNetworks() {
        var _that = this;
        var url: string;
        url = "/account_api"
        this._dataservice.getDataByUrl(url)
          .subscribe(
            res => _that.socialNetworks = res,
            err => _that.logError(err)
          )
      }
    

    【讨论】:

    • 嗯,这消除了错误,但现在它没有显示任何内容(它应该)。所以我假设它是一个永远不会改变的空数组。
    • 您的 _dataservice 成功返回什么?
    • 它只是返回一个字典对象数组。我应该补充一点,我已成功获取数据,并且在我的 html 代码的 for 循环中,它确实按我的预期生成了一个列表。
    • 观看/记录 this.socialNetworks 显示值的任何变化?
    • 它更改为应有的 socialNetwork 数组,我可以通过调试器看到它​​,但如果我尝试执行 console.log(this.socialNetworks),它总是显示未定义。
    【解决方案2】:

    如果 api 调用使用了一些外部库,它可能不会被挂接到 Angular 2 的摘要循环中(例如,Facebook SDK 不是)。您可以使用Augury 进行调试,或者为简单起见,在您的构造函数中设置一个全局窗口属性来访问您的组件:

    constructor(private _dataservice: DataService) {
      window['MAC'] = this;
    }
    

    然后你可以在浏览器的开发工具中查看socialNetworks数组是否真的被设置了:

    MAC.socialNetworks
    

    您总是可以在您的 HTML 中使用一些快速代码将其显示为 JSON 以调试正在发生的事情:

    {{socialNetworks | json}}
    

    如果页面没有显示它具有值,但您在控制台中看到它,那么您的 _dataService 不会触发更改检测,您必须手动执行此操作。您可以通过在构造函数中注入 ApplicationRef 并在设置数据后对其调用 tick() 来使用它。

    constructor(
        private _dataservice: DataService,
        private _appref: ApplicationRef ) {
    }
    
    getSocialNetworks() {
        var _that = this;
        var url: string;
        url = "/account_api"
        this._dataservice.getDataByUrl(url)
          .subscribe(
            res => {
                _that.socialNetworks = res;
                this._appref.tick(); // force change detection
            }, err => _that.logError(err)
    )
    }
    

    至于calling length on undefined,由于您正在异步提取数据,因此您的socialNetworks 属性在开始时是未定义的。您可以将其初始化为一个空数组,就像@JacobS 的答案一样,或者修改您的支票以解决它:

    <div *ngIf="socialNetworks && socialNetworks.length > 1">
    

    【讨论】:

    • 它正在设置值,我确实知道这一点。但我认为您在变更检测部分可能是正确的。但我不完全确定如何正确地做到这一点。它会在该单个组件的构造函数中正确吗?
    • 我为此添加了代码,ApplicationRef 是您可以像数据服务一样注入的服务,您可以在设置结果以强制更改检测以更新 UI 后调用tick()。 ,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 2019-04-08
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多