在我的Angular 2应用程序中,我收到一个错误:

无法读取未定义的属性‘Title’.

这是一个非常简单的组件,只是试图得到一个最低限度的工作在这里.它击中了我的API控制器(奇怪的是多次),并且似乎在返回对象后击中了回调.我的控制台.日志(log)输出我期望的对象.以下是全部错误:

TypeError: Cannot read property 'title' of undefined
    at AbstractChangeDetector.ChangeDetector_About_0.detectChangesInRecordsInternal (eval at <anonymous> (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:10897:14), <anonymous>:31:26)
    at AbstractChangeDetector.detectChangesInRecords (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8824:14)
    at AbstractChangeDetector.runDetectChanges (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8807:12)
    at AbstractChangeDetector._detectChangesInViewChildren (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8877:14)
    at AbstractChangeDetector.runDetectChanges (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8811:12)
    at AbstractChangeDetector._detectChangesContentChildren (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8871:14)
    at AbstractChangeDetector.runDetectChanges (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8808:12)
    at AbstractChangeDetector._detectChangesInViewChildren (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8877:14)
    at AbstractChangeDetector.runDetectChanges (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8811:12)
    at AbstractChangeDetector.detectChanges (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:8796:12)

服务(about.service.ts):

import {Http} from 'angular2/http';
import {Injectable} from 'angular2/core';
import {AboutModel} from './about.model';
import 'rxjs/add/operator/map';

@Injectable()
export class AboutService {
    constructor(private _http: Http) { }

    get() {
        return this._http.get('/api/about').map(res => {
            console.log(res.json()); // I get the error on the line above but this code is still hit.
            return <AboutModel>res.json();
        });
    }
}

组件(关于.Component.ts):

import {Component, View, OnInit} from 'angular2/core';
import {AboutModel} from './about.model';
import {AboutService} from './about.service';
import {HTTP_PROVIDERS} from 'angular2/http';

@Component({
    selector: 'about',
    providers: [HTTP_PROVIDERS, AboutService],
    templateUrl: 'app/about/about.html'
})

export class About implements IAboutViewModel, OnInit {
    public about: AboutModel;

    constructor(private _aboutService: AboutService) {}

    ngOnInit() {    
        this._aboutService.get().subscribe((data: AboutModel) => {
            this.about = data;
        });
    }
}

export interface IAboutViewModel {
    about: AboutModel;
}

指数html

<script src="~/lib/systemjs/dist/system.src.js"></script>
<script src="~/lib/angular2/bundles/router.js"></script>
<script src="~/lib/angular2/bundles/http.js"></script>
<script src="~/lib/angular2/bundles/angular2-polyfills.js"></script>
<script src="~/lib/angular2/bundles/angular2.dev.js"></script>
<script src="~/lib/es6-shim/es6-shim.js"></script>
<script>
    System.config({
        packages: {
            app: {
                format: 'register',
                defaultExtension: 'js'
            },
            rxjs: {
                defaultExtension: 'js'
            }
        },
        map: {
            rxjs: "lib/rxjs"
        }
    });
    System.import('app/boot')
            .then(null, console.error.bind(console));
</script>

推荐答案

请在下次提供您的视图和模型(app/about/about.html和about.model).

如果返回array,可以使用asyncPipe,它"订阅一个可观察或promise ,并返回它发出的最新值.当发出一个新值时,异步管道会标记要判断的组件以进行更改",因此视图将用新值更新.

如果返回primitive type(字符串、数字、布尔值),也可以使用asyncPipe.

如果您返回的是object我不知道如何使用异步管道,我们可以将异步管道与safe navigation operator ?.结合使用,如下所示:

{{(objectData$ | async)?.name}}

但这看起来有点复杂,我们必须对每个要显示的对象属性重复这一点.

正如@Pixelbits在注释中提到的那样,您可以将subscribe()赋给控制器中的可观察对象,并将包含的对象存储到组件属性中.然后在模板中使用安全导航操作符或NgIf:

service.ts

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import 'rxjs/add/operator/map';  // we need to import this now

@Injectable()
export class MyService {
  constructor(private _http:Http) {}
  getArrayData() {
    return this._http.get('./data/array.json')
      .map(data => data.json());
  }
  getPrimitiveData() {
    return this._http.get('./data/primitive.txt')
      .map(data => data.text());   // note .text() here
  }
  getObjectData() {
    return this._http.get('./数据/对象.json')
      .map(data => data.json());
  }
}

app.ts

@Component({
  selector: 'my-app',
  template: `
    <div>array data using '| async':
      <div *ngFor="let item of arrayData$ | async">{{item}}</div>
    </div>
    <div>primitive data using '| async': {{primitiveData$ | async}}</div>
    <div>object data using .?: {{objectData?.name}}</div>
    <div *ngIf="objectData">object data using NgIf: {{objectData.name}}</div>`
  providers: [HTTP_PROVIDERS, MyService]
})
export class AppComponent {
  constructor(private _myService:MyService) {}
  ngOnInit() {
    this.arrayData$     = this._myService.getArrayData();
    this.primitiveData$ = this._myService.getPrimitiveData();
    this._myService.getObjectData()
      .subscribe(data => this.objectData = data);
  }
}

data/array.json

[ 1,2,3 ]

数据/原语.json

Greetings SO friends!

数据/对象.json

{ "name": "Mark" }

输出:

array data using '| async':
1
2
3
primitive data using '| async': Greetings SO friends!
object data using .?: Mark
object data using NgIf: Mark

Plunker

Angular相关问答推荐

在Angular中使用ngFor进行表乘法

一个接一个的Angular http请求,但只关心第一个

ION标签-从子对象中加载页,保留父对象的S内容

Angular 懒惰地加载一个服务

如何正确导出/导入枚举和接口文件以便 Jest 成功完成测试?

相同的 Angular 代码在生产环境中停止工作

PrimeNG 避免在同一位置使用不同键的 cogo toast 重叠

应该显示在表格中的嵌套循环

没有调用订阅的原因是什么?

Angular:如何在根组件中使用 ngx-translate?

不再需要 core-js 了吗?

使用 NPM 安装 Font Awesome 5

Angular [disabled]="MyBoolean" 没有工作

如何处理解析器中的错误

Angular 6 - NullInjectorError:单元测试中没有 HttpClient 的提供者

angular 2模板使用console.log

Angular 2 组件不是任何 NgModule 的一部分

Angular2material对话框自动关闭

如何在功能模块层次 struct 中使用 .forRoot()

Angular CLI 为已经存在的组件创建 .spec 文件