Errore di tipo osservabile: imansible leggere la proprietà di non definito

Applicazione Angular 2, ottengo un errore: imansible leggere la proprietà ‘title’ di undefined. Questo è un componente molto semplice, solo cercando di ottenere il minimo indispensabile per lavorare qui. Colpisce il mio controller API (curiosamente più volte), e sembra colpire l’area nel mio codice che è il callback dopo che un object è stato restituito. Il mio console.log restituisce l’object che mi aspetterei. Ecco l’errore completo:

TypeError: Cannot read property 'title' of undefined at AbstractChangeDetector.ChangeDetector_About_0.detectChangesInRecordsInternal (eval at  (http://localhost:55707/lib/angular2/bundles/angular2.dev.js:10897:14), :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) 

Il servizio (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 res.json(); }); } } 

The Component (about.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; } 

index.html

        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));  

Per favore includi la tua vista e modella la prossima volta (app / about / about.html e about.model).

Se si restituisce un array , è ansible utilizzare asyncPipe , che “sottoscrive un Observable or Promise e restituisce il valore più recente emesso. Quando viene emesso un nuovo valore, la pipe async contrassegna il componente da verificare per le modifiche”, quindi la vista verrà aggiornata con il nuovo valore.

Se si restituisce un tipo primitivo (stringa, numero, booleano) è ansible utilizzare anche asyncPipe.

Se stai restituendo un object , non sono a conoscenza di alcun modo di usare asyncPipe , potremmo usare la pipe async, in congiunzione con l’ operatore di navigazione sicura ?. come segue:

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

Ma sembra un po ‘complicato, e dovremmo ripeterlo per ogni proprietà dell’object che volevamo mostrare.

Come @pixelbits menzionato in un commento, puoi subscribe() all’osservabile nel controller e memorizzare l’object contenuto in una proprietà del componente. Quindi utilizzare l’operatore di navigazione sicura o NgIf nel modello:

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('./data/object.json') .map(data => data.json()); } } 

app.ts

 @Component({ selector: 'my-app', template: ` 
array data using '| async':
{{item}}
primitive data using '| async': {{primitiveData$ | async}}
object data using .?: {{objectData?.name}}
object data using NgIf: {{objectData.name}}
` 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); } }

Dati / array.json

 [ 1,2,3 ] 

Dati / primitive.json

 Greetings SO friends! 

Dati / object.json

 { "name": "Mark" } 

Produzione:

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

Plunker

Sembra che tu abbia indicato about.title nella vista about.html ma la variabile about viene creata solo dopo che la richiesta http è stata completata. Per evitare questo errore puoi avvolgere about.html con

...

La risposta precedente è corretta. È necessario verificare se la variabile è definita prima di utilizzarla nel modello. Utilizzando la richiesta HTTP è necessario del tempo per definirlo. utilizzare * ngIf per verificare. L’esempio è fornito da angular con https://angular.io/docs/ts/latest/tutorial/toh-pt5.html e l’esempio è http://plnkr.co/edit/?p=preview

 

{{hero.name}} details!

Puoi controllare app / hero-detail.component [ts e html]