angular - observables - Error de tipo observable: no se puede leer la propiedad de indefinido
subscribe angular 4 (3)
Incluya su vista y modelo la próxima vez (app / about / about.html y about.model).
Si está devolviendo una matriz , puede usar el asyncPipe , que "se suscribe a un Observable o Promesa y devuelve el último valor que ha emitido. Cuando se emite un nuevo valor, la tubería asíncrona marca el componente para verificar los cambios". la vista se actualizará con el nuevo valor.
Si devuelve un tipo primitivo (cadena, número, booleano), también puede usar asyncPipe.
Si está devolviendo un
objeto
,
no conozco ninguna forma de usar asyncPipe
, ¿podríamos usar la tubería asíncrona, junto con el
operador de navegación segura
?.
como sigue:
{{(objectData$ | async)?.name}}
Pero eso parece un poco complicado, y tendríamos que repetir eso para cada propiedad de objeto que queramos mostrar.
Como @pixelbits mencionó en un comentario, puede
subscribe()
a lo observable en el controlador y almacenar el objeto contenido en una propiedad de componente.
Luego use el operador de navegación segura o NgIf en la plantilla:
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: `
<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 ]
data / primitive.json
Greetings SO friends!
data / object.json
{ "name": "Mark" }
Salida:
array data using ''| async'':
1
2
3
primitive data using ''| async'': Greetings SO friends!
object data using .?: Mark
object data using NgIf: Mark
En mi aplicación Angular 2, aparece un error:
No se puede leer la propiedad ''título'' de indefinido.
Este es un componente muy simple, solo tratando de obtener un mínimo para trabajar aquí. Golpea mi controlador API (curiosamente varias veces), y parece golpear la devolución de llamada después de que se devuelve un objeto. Mi console.log genera el objeto que esperaría. Aquí está el error completo:
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)
El servicio (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();
});
}
}
El componente (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
<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>
La respuesta anterior es correcta. Debe verificar si la variable está definida antes de usarla en su plantilla. Usando la solicitud HTTP, necesita tiempo para definirla. use * ngIf para verificar. El ejemplo se proporciona desde angular con https://angular.io/docs/ts/latest/tutorial/toh-pt5.html y el ejemplo es http://plnkr.co/edit/?p=preview
<div *ngIf="hero">
<h2>{{hero.name}} details!</h2>
<div>
Puede consultar app / hero-detail.component [ts y html]
Parece que se ha referido a
about.title
en la vista
about.html
pero la variable
about
solo se instancia una vez que se completa la solicitud
http
.
Para evitar este error, puede envolver
about.html
con
<div *ngIf="about"> ... </div>