Alan Stephens Alan Stephens - 1 month ago 18
TypeScript Question

Response.json() bind to single object using interface - RxJs/Observable fails

This scenario works fine when the RESTful API returns a JSON array - but the web method I'm calling returns a single JSON object - and so the code has been converted to map a single object from

<IRegistration[]> to <IRegistration>
all the way up the stack.

This fails and the Chrome console returns an error showing the app could not find either of the mapped fields in the HTML

The HTML

{{myobject.productId}}
{{myobject.productName}}


The JSON

{
"productId": 1,
"productName": "My Field Value"
}


The Interface

export interface IRegistration {
productId: number;
productName: string;
}


The observable

getRegistration(): Observable<IRegistration> {
return this._http.get(this._svcURL)
.map((response: Response) => <IRegistration>response.json())
.do(data => console.log('ALL: ' + JSON.stringify(data)))
.catch(this.handleError);
}


The client component

myobject: IRegistration;

ngOnInit(): void {
this._registrationService.getRegistration().subscribe(
reg => this.myobject= reg,
error => this.errorMessage = <any>error
);
}


The error

EXCEPTION: TypeError: Cannot read property 'productId' of undefined in [
{{myobject.productId}}
{{myobject.productName}}

in SearchComponent@0:0]


The debugging I've done points to the response.json() in the observable failing to map correctly to the IRegistration - I can't seem to find the correct syntax?

Answer

The code looks fine, I think the problem is that you don't initialize the myobject: IRegistration; before using it.

The doc for lifecycle hook ngOnInit() says:

Initialize the directive/component after Angular first displays the data-bound properties and sets the directive/component's input properties.

The data is displayed before the HTTP call returns any result so myobject is undefined when Angular is trying to render it.

You can use ? to ignore undefined properties such as {{ myobject?.productId }} or initialize the property first myobject: IRegistration = <IRegistration>{};.