Search code examples
angulartypescriptes6-promise

Angular 2 - Unhandled Promise when injecting a service


I've tried to start a project from the official tutorial and I'm having a problem injecting services in my Angular2 app. everything goes fine until I add a service. Here are the files :

app.component.ts

import { Component, OnInit } from '@angular/core';

import { client }  from './client/client';
import { clientService } from './client/client.service';

@Component({
    selector: 'my-app',
    template: `
    <nav>
        <h1>{{title}}</h1>
        <h2>client n° {{client.id}}</h2>
    </nav>
    <client-detail [client]="client"></client-detail>
    `,
    providers: [clientService]
})

export class AppComponent implements OnInit { 
    title = "client gendarmerie";
    client: client;

    constructor(private clientService: clientService) { }

    getclient(): void {
        this.clientService.getclient().then(client_eg => this.client = client_eg);
    }
    ngOnInit(): void {
        this.getclient();
    }
}

service/client.service

import { Injectable } from '@angular/core';

import { client } from './client';
import { client_EG } from './mock-client';

@Injectable()
export class clientService {
    getclient(): Promise<client> {
        return Promise.resolve(client_EG);
    }
}

client/mock-client

import { client } from './client';

export const client_EG: client = {
    id:parseInt('10243'),
    contact: {
        phone: parseInt('0606060606'),
        access: ["Localisation", "chat", "picture"]
    },
};

Without the service, everything goes fine. Here is the error I get when trying to launch the app:

core.umd.js:3462 EXCEPTION: Error in ./AppComponent class AppComponent
- inline template:3:12 caused by: Cannot read property 'id' of undefinedErrorHandler.handleError @ core.umd.js:3462(anonymous function) @ core.umd.js:6860ZoneDelegate.invoke @ zone.js:203NgZoneImpl.inner.inner.fork.onInvoke @ core.umd.js:6242ZoneDelegate.invoke @ zone.js:202Zone.run @ zone.js:96(anonymous function) @ zone.js:462ZoneDelegate.invokeTask @ zone.js:236NgZoneImpl.inner.inner.fork.onInvokeTask @ core.umd.js:6233ZoneDelegate.invokeTask @ zone.js:235Zone.runTask @ zone.js:136drainMicroTaskQueue @ zone.js:368ZoneTask.invoke @ zone.js:308 core.umd.js:3464 ORIGINAL EXCEPTION: Cannot read property 'id' of undefined

Solution

  • Because of initial change detection tick on view it is trying to evaluate client.id expression, where client value is undefined. Because the promise for getclient method haven't gets resolved yet.

    You could use Elvis Operator like client?.id and then have ngIf directive to hide client-detail Component to client object gets populated

    Markup

    <nav>
        <h1>{{title}}</h1>
        <h2>client n° {{client?.id}}</h2>
    </nav>
    <client-detail *ngIf="client" [client]="client"></client-detail>