javascript - Angular2 - TypeError: Kann Eigenschaft 'Id' von undefiniert in (Typescript) nicht lesen
Ich erhalte den folgenden Fehler:
angular2.dev.js:23925 EXCEPTION: TypeError: Cannot read property 'Id' of null in [
{{ product.Id }}
in ProductEditComponent@0:68]
geworfen mit:
//Product-edit.component.ts:
import {Component } from 'angular2/core';
import { IProduct } from './product'
import { ProductService } from './product.service'
import { RouteParams } from 'angular2/router';
@Component({
template:`<div class="wrapper wrapper-content animated fadeInRight ecommerce">
{{ product.Id }}
</div>`,
})
export class ProductEditComponent{
product: IProduct = null;
errorMessage: string;
constructor(private _routeParams: RouteParams, private _productService: ProductService){
}
ngOnInit(): void {
this._productService.getProduct(this._routeParams.get('id'))
.subscribe(
product => this.product = product,
error => this.errorMessage = <any>error);
}
}
Produktdienstleistung:
getProduct(id: string): Observable<IProduct> {
return this._http.get(this._baseUrl + this._getProductUrl + '/' + id)
.map((response: Response) => <IProduct>response.json())
.do(data => console.log("All: " + JSON.stringify(data)))
.catch(this.handleError);
}
Antwort vom Server:
{"Id":"34d4efcy6","ExternalId":null,"UserId":"testing","ProductProvider":null,"Title":"Flaska vin","Desc":null,"MinDeliveryTime":null,"MaxDeliveryTime":null,"FreightCost":null,"Brand":null}
Was vermassel ich?
Antwort #1
In Ihrer Komponente initialisieren Sie product mit null und referenzieren dann product.Id in Ihrer Vorlage. Der Fehler tritt auf, wenn Angular versucht, Ihre Vorlage zunächst zu rendern, bevor Ihr asynchroner Aufruf zurückkehrt - zu diesem Zeitpunkt ist product noch null, daher der Fehler: Cannot read property 'Id' of null.
Die unmittelbarste Lösung ist die Verwendung des Elvis-Operators, den Angular für genau solche Situationen bereitstellt. Sie würden ihn verwenden, indem Sie {{ product.Id }} in Ihrer Vorlage durch {{ product?.Id }} ersetzen.
Allerdings werden Sie bei diesem Ansatz wahrscheinlich auf Probleme bei der Änderungserkennung stoßen, und im Allgemeinen sind Sie mit einem Ansatz wie dem folgenden viel besser dran:
export class ProductEditComponent{
product: Observable<IProduct>; //product is an Observable
errorMessage: string;
constructor(private _routeParams: RouteParams, private _productService: ProductService){
//product is always defined because you instantiate it in the ctor
this._productService.getProduct(this._routeParams.get('id'));
}
Sie würden dann {{(product | async).Id }} anstelle von {{product.Id}} in Ihrer Vorlage verwenden und AsyncPipe nutzen, damit Angular die mühsame Arbeit des Abonnierens und Aktualisierens der Benutzeroberfläche bei Bedarf für Sie übernimmt.
