3

I am trying to make a get request using the Http module in Angular2 (angular 2.0.0-beta.0 and typescript 1.7.5), but I have some kind of synchronise problem. I put everything in one .ts file to make it easier to communicate.

Everything compiles fine in typescript but Chrome shows the following error the in console :

EXCEPTION: TypeError: Cannot read property '_id' of undefined in [Id: {{contact._id}} Name: {{contact.name}} in Test@1:13]
ORIGINAL EXCEPTION: TypeError: Cannot read property '_id' of undefined
ORIGINAL STACKTRACE:
TypeError: Cannot read property '_id' of undefined
...
...
Object {_id: "5695e53d98ff94671ae22d55", name: "Piet Pannenkoek", email: "[email protected]", number: "435345"}

test1.ts:

import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core';
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/Rx';

@Component({
    selector: 'my-app',
    template: `
        <div>Id: {{contact._id}} Name: {{contact.name}}</div>
    `,
    providers: [HTTP_PROVIDERS]
})

export class Test {

    public contact: Contact;

    constructor(private http: Http) {}

    ngAfterViewInit() {
        this.http.get('/api/contactlist/5695e53d98ff94671ae22d55')
            .map((res: Response) => res.json())
            .subscribe(res => {
                console.log(res);
                this.contact = res;
            });
    }
}

export class Contact {
    constructor (public _id: string, public name: string, public email: string, public number: string) {};
}

bootstrap(Test);

http://localhost:3000/api/contactlist/5695e53d98ff94671ae22d55

{"_id":"5695e53d98ff94671ae22d55","name":"Piet Pannenkoek","email":"[email protected]","number":"435345"}

Strange is that another (little different) version test2.ts doesn't give any errors:

import {bootstrap} from 'angular2/platform/browser';
import {Component} from 'angular2/core';
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';
import 'rxjs/Rx';

@Component({
    selector: 'my-app',
    template: '<div *ngFor="#contact of contacts">Id: {{contact._id}} Name: {{contact.name}}</div>',
    providers: [HTTP_PROVIDERS]
})

export class Test {

    public contacts: Contact[] = [];

    constructor(private http: Http) {}

    ngAfterViewInit() {
        this.http.get('/api/contactlist')
            .map((res: Response) => res.json())
            .subscribe(res => {
                console.log(res);
                this.contacts = res;
            });
    }
}

export class Contact {
    constructor (public _id: string, public name: string, public email: string, public number: string) {};
}

bootstrap(Test);

http://localhost:3000/api/contactlist

[{"_id":"5695e53d98ff94671ae22d55","name":"Piet Pannenkoek","email":"[email protected]","number":"435345"},{"_id":"56a63059b2cb5f4b10efaf9a","name":"Jan Janssen","email":"[email protected]","number":"642"},{"_id":"56a6307bb2cb5f4b10efaf9b","name":"Gerard de Boer","email":"[email protected]","number":"1234"},{"_id":"56abe853211b52a441f6c45f","name":"Bjorn Borg","email":"[email protected]","number":"123"},{"_id":"56abe8da211b52a441f6c460","name":"Hans Dobbelsteen","email":"[email protected]","number":"752"},{"_id":"56abe8fe211b52a441f6c461","name":"Marco van Basten","email":"[email protected]","number":"961"}]

3 Answers 3

3

You are trying to use contact object before it's resolved. Either use elvis-operator {{ contact?._id }} or show block conditionally:

template: `
    <div *ngIf="contact">Id: {{contact._id}} Name: {{contact.name}}</div>
`,
Sign up to request clarification or add additional context in comments.

Comments

2

you are trying to access contact object whihc is undefined/null till the template load i.e your object has not loaded properly at the time of template load. so to avoid this you have to use elvis operator like following

{{contact?._id}} and {{contact?.name}}

by using elvis operator angualr will not throw any error if your contact object has no value named name or id. whenever your binding load properly to contact Object angular will reflact changes to template.

try this one surely work for you.

<div>Id: {{contact?._id}} Name: {{contact?.name}}</div>

2 Comments

but this answer content is already covered by Günter Zöchbauer.. no need to add it again, if you wanted to add same thing again..
in my answer i explained about elvis operator which is required as answer so that's y posted as asnwer
1

Angular tries to bind before the data arrived.

<div>Id: {{contact?._id}} Name: {{contact?.name}}</div>

should work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.