Jamshed Jamshed - 5 months ago 26
TypeScript Question

Service observable not working in Component NgOnInIt - Angular2

My getHero service observable is not getting invoked in NgOnInIt in the HeroDetail Component.

I'm able to use HTTP to get & display the data table & route to a detail page when the row is clicked. Then I'm using the url's "id" parameter to get the id but the same is not working with the getHero function to get the particular row details.

ID is shown in console but hero comes as undefined. I've tried a lot of stuffs but none has worked so far. Any help would be highly appreciated.

Below is my code for reference.

hero.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Hero } from './hero';

@Injectable()
export class HeroService {
heroes: Hero[];
hero: Hero;

private heroesUrl = 'SERVICE URL';
constructor (private http: Http) {}

getHeroes(): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json()['data'];
console.log(body);
return body || { };
}
private handleError (error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}

getHero(id: number): Observable<Hero> {
return this.getHeroes()
.map(heroes => heroes.find(hero => hero.cc_id == id));
}
}


hero-detail.component.ts

import { Component } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';
import { HeroService } from './hero.service';
import { Hero } from './hero';

@Component({
template: `
<h2>INNER PAGE {{ this.id }}</h2>
`,
providers: [HeroService]
})

export class HeroDetailComponent {

errorMessage: string;
hero: Hero;
heroes: Hero[];
id: number;
mode = 'Observable';

constructor (
private service: HeroService,
private route: ActivatedRoute,
private router: Router
) {}


ngOnInit() { this.getHeroes() }

getHeroes() {
this.id = this.route.snapshot.params['id'];
console.log(this.id);

this.service.getHero(this.id).subscribe(hero => this.hero = hero);
console.log(this.hero);
}

}

Answer Source

You are logging this.hero before call is done. This is because Http calls are done asynchronous.

getHeroes() {
    this.id = this.route.snapshot.params['id'];
    console.log(this.id);

    this.service.getHero(this.id).subscribe(hero => {
         this.hero = hero;
         console.log(this.hero);
    });
}