【问题标题】:Angular2 - interpolated object is 'undefined' but console.log() worksAngular2 - 插值对象是“未定义”,但 console.log() 有效
【发布时间】:2016-12-22 22:57:47
【问题描述】:

我正在开发一个非常简单的 Angular2 应用程序,但我遇到了一个问题,即插值组件对象被浏览器评估为 undefined,尽管我能够在组件中 console.log(this) 并查看这些值,尽管带有“刚刚评估以下值”的注释。

就上下文而言,我已经使用 Angular2 命令行工具启动了我的应用程序,但我大致遵循 Angular2 'Tour of Heroes' 教程(它使用压缩的快速入门包来组装基本文件)...

导致问题的模板是person-detail.component.html,我很简单:

<div>Welcome, {{ person.name }}</div>

这里是关联的person-detail.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute, Params }   from '@angular/router';
import { Location }                 from '@angular/common';
import 'rxjs/add/operator/switchMap';
import { PersonService } from './person.service';
import { Person } from './person';

@Component({
  selector: 'person-details',
  templateUrl: './person-details.component.html'
})

export class PersonDetailsComponent implements OnInit {

  @Input() person: Person;
   constructor(
    private personService: PersonService,
    private route: ActivatedRoute,
    private location: Location
  ) {};

  ngOnInit(): void {
    this.route.params
      .switchMap((params: Params) => this.personService.getPerson(+params['id']))
      .subscribe(person => this.person = person);

      console.log(this) //THIS LOGS THE COMPLETE OBJECT AS I WANT IT, BUT WITH THE 'Value below...' NOTE
  };
}

person.service.ts

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions, Response } from '@angular/http';
import 'rxjs/add/operator/map';
import { Observable } from "rxjs/Observable";
import { Person } from './person';
import 'rxjs/add/operator/toPromise';

@Injectable()
export class PersonService {
    private apiUrl = 'http://localhost:4000/api/';

    constructor(private http: Http) {
        console.log('Service ready...');
    }

  getPeople(): Promise<Person[]> {
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });
    return this.http
      .get(this.apiUrl + 'people', options)
      .toPromise()
      .then(response => response.json().data as Person[])
  }

  getPerson(id: number): Promise<Person> {
    return this.getPeople()
      .then(people => people.find(person => person.id === id));
  }  
}

但是当我导航到页面时,我收到错误inline template:0:5 caused by: Cannot read property 'name' of undefined,尽管console.log() 返回的数据看起来不错。

从概念上讲,我了解正在发生的事情......页面的部分在对象完全形成之前呈现。但我很困惑,因为据我所知,我以与“英雄之旅”教程完全相同的方式将所有东西放在一起,效果很好——除了我用命令行启动我的项目工具(构建项目略有不同),我正在使用一些标头选项等连接到我自己的 API...

如何设置它,以便页面部分等到对象完全形成后再尝试呈现它?

注意 - 如果我尝试插入 {{ person }},浏览器会显示 [object Object]

【问题讨论】:

  • console.log(person) 而不是console.log(this) 它给了你什么?
  • console.log(person) 是一个错误,但console.log(this.person) 记录undefined
  • 但是console.log(this)是一个完整的对象,带有person属性

标签: angular


【解决方案1】:

console.log 给您的印象是错误的,因为当您尝试在模板中访问它时,person 仍然是 undefined,尽管您没有时间欣赏控制台中的更改,如果来自服务器的响应足够快。所以你需要使用safe navigation operator

<div>Welcome, {{ person?.name }}</div>

【讨论】:

    【解决方案2】:

    在某些情况下,您可能需要考虑使用typescript getters。它们将允许您为属性设置默认值。

    export class PersonDetailsComponent implements OnInit {
      @Input() personInput: Person;
      get person(){
        return personInput || {};
      }
    

    这样称呼:

    <person-details [personInput]="details"></person-details>
    

    然后在你的 PersonDetailsComponent 中,你就可以直接使用它了:

    <div>Welcome, {{ person.name }}</div>
    

    【讨论】:

      猜你喜欢
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-14
      • 1970-01-01
      • 1970-01-01
      • 2020-04-22
      • 1970-01-01
      相关资源
      最近更新 更多