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

4
  • any error in console? Commented Mar 28, 2017 at 2:38
  • open your console, maybe you can see error about "CORS" in here. Commented Mar 28, 2017 at 2: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] (localhost:4200/vendor.bundle.js:13612:21) Commented Mar 28, 2017 at 3:22
  • 1
    Can you try using the safe-navigation operator? Like this: <p> {{ theData?. classroom?.Id }}</p> Commented Mar 28, 2017 at 5:28

1 Answer 1

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);
   }
Sign up to request clarification or add additional context in comments.

1 Comment

I've added to this on the app.component.html <p> {{ theData?. classroom.Id }}</p> . This allows to wait for the data a?.b.c which would short circuit further evaluation if a is null.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.