0

I’m new in Angular 2 and I’m playing with the environment to create some app. Doing the things like the site Angular.io says I’m able to create an Injectable Service and using it on my AppComponent but only If I read the data from the same .ts file like this.sourceData = {…}. If I get the json data from a Rest service the data is undefined

app.service.ts

Import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

@Injectable()
export class WebService {
    private dataUrl = 'http://localhost:8080/api/home';
    constructor(private http: Http) { }
    getData() : Observable<any> {
        return this.http.get(this.dataUrl)
            .map(this.extractData)
            .catch(this.handleError);
   }
    private extractData(res: Response) {
        let body = res.json();
        return body.data || {};
    }

app.component.ts

import { Component, OnInit } from '@angular/core';
import { WebService } from './app.service';

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    providers: [WebService]

})
export class AppComponent implements OnInit {
    errorMessage: string;
    theData: Object;
    constructor(private dataService: WebService) {}

    ngOnInit() { this.getDataFromService(); }
    getDataFromService() {
        this. dataService. getData ()
            .subscribe(
            myData => this.theData = myData,
            error => this.errorMessage = <any>error);
    }    
}

app.component.html

<p> {{ theData. classroom.Id }}</p>

JSON from service

{
    "classroom": {
        "Id": "01",
        "totalStudents": "2",

        "Students": [{
            "Name": "Jhon",
            "age": "18"
        }, {
            "Name": "Doe",
            "age": "18"
        }],
        "Teachers": [{
            "Name": "Jane",
            "age": "38"
        }, {
            "Name": "Doe",
            "age": "35"
        }]
    }
}

Am I missing something when using Observables? Thanks in advance

AT82
  • 71,416
  • 24
  • 140
  • 167
CREM
  • 1,929
  • 1
  • 25
  • 35
  • any error in console? – Aniruddha Das Mar 28 '17 at 02:38
  • open your console, maybe you can see error about "CORS" in here. – Tiep Phan Mar 28 '17 at 02:48
  • It's not a CORS problem, that I already fixed it. The first error on the console it's: ERROR TypeError: Cannot read property ' classroom' of undefined at Object.eval [as updateRenderer] (ng:///AppModule/AppComponent.ngfactory.js:25:34) at Object.debugUpdateRenderer [as updateRenderer] (http://localhost:4200/vendor.bundle.js:13612:21) – CREM Mar 28 '17 at 03:22
  • 1
    Can you try using the safe-navigation operator? Like this: `

    {{ theData?. classroom?.Id }}

    `
    – eko Mar 28 '17 at 05:28

1 Answers1

1

When you call response.json(), it automatically grabs the data property from the ajax response and returns it, so remove your reference to .data in your extractData method.

getData() : Observable<any> {
        return this.http.get(this.dataUrl)
            .map(this.extractData)
            .catch(this.handleError);
   }
    private extractData(res: Response) {
        return res.json();
        //return body.data || {};  // <-- this line needs to go
    }

FYI, because your extractData method is reduced to one line, most example (and real life) code will just inline that call in your map function

 getData() : Observable<any> {
        return this.http.get(this.dataUrl)
            .map(response => response.json())
            .catch(this.handleError);
   }
snorkpete
  • 14,278
  • 3
  • 40
  • 57
  • I've added to this on the app.component.html

    {{ theData?. classroom.Id }}

    . This allows to wait for the data a?.b.c which would short circuit further evaluation if a is null.
    – CREM Mar 30 '17 at 02:07