Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I have a problem with HTTP in Angular 2.

I just want to GET a JSON list and show it in the view.

Service class

import {Injectable} from "angular2/core";
import {Hall} from "./hall";
import {Http} from "angular2/http";
@Injectable()
export class HallService {
    public http:Http;
    public static PATH:string = 'app/backend/'    

    constructor(http:Http) {
        this.http=http;
    }

    getHalls() {
           return this.http.get(HallService.PATH + 'hall.json').map((res:Response) => res.json());
    }
}

And in the HallListComponent I call the getHalls method from the service:

export class HallListComponent implements OnInit {
    public halls:Hall[];
    public _selectedId:number;

    constructor(private _router:Router,
                private _routeParams:RouteParams,
                private _service:HallService) {
        this._selectedId = +_routeParams.get('id');
    }

    ngOnInit() {
        this._service.getHalls().subscribe((halls:Hall[])=>{ 
            this.halls=halls;
        });
    }
}

However, I got an EXCEPTION:

TypeError: this.http.get(...).map is not a function in [null]

hall-center.component

import {Component} from "angular2/core";
import {RouterOutlet} from "angular2/router";
import {HallService} from "./hall.service";
import {RouteConfig} from "angular2/router";
import {HallListComponent} from "./hall-list.component";
import {HallDetailComponent} from "./hall-detail.component";
@Component({
    template:`
        <h2>my app</h2>
        <router-outlet></router-outlet>
    `,
    directives: [RouterOutlet],
    providers: [HallService]
})

@RouteConfig([
    {path: '/',         name: 'HallCenter', component:HallListComponent, useAsDefault:true},
    {path: '/hall-list', name: 'HallList', component:HallListComponent}
])

export class HallCenterComponent{}

app.component

import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES} from "angular2/router";
import {RouteConfig} from "angular2/router";
import {HallCenterComponent} from "./hall/hall-center.component";
@Component({
    selector: 'my-app',
    template: `
        <h1>Examenopdracht Factory</h1>
        <a [routerLink]="['HallCenter']">Hall overview</a>
        <router-outlet></router-outlet>
    `,
    directives: [ROUTER_DIRECTIVES]
})

@RouteConfig([
    {path: '/hall-center/...', name:'HallCenter',component:HallCenterComponent,useAsDefault:true}
])
export class AppComponent { }

tsconfig.json

{
  "compilerOptions": {
    "target": "ES5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules"
  ]
}

Sorry for the long post...

share|improve this question
    
Doesn't http.get return a promise? – bmm6o Dec 29 '15 at 16:38
1  
@bmm6o The new Http service returns an observable – Brocco Dec 29 '15 at 16:39
    
I ran into a nearly identical issue, trying to migrate a project from Angular2 beta-17 to final release. The issue for me was my IDE though, using VS 2015, Update 3. The TypeScript language service extension was still at 1.8.36, whereas as the ng2 quickstart guide (as I write this) is using "typescript": "^2.0.2". Upgrading the TS lang. service via Extensions and Updates did the trick for me. While that update was being installed I came across this SO answer, which ends with the same conclusion. – Eric Lease Sep 21 at 7:03
up vote 199 down vote accepted

I think that you need to import this:

import 'rxjs/add/operator/map'

Or more generally this if you want to have more methods for observables:

import 'rxjs/Rx';

See this issue for more details.

share|improve this answer
1  
Which errors still remain? You can ask some specific questions regarding this on stackoverflow ;-) This question could perhaps help you as well: stackoverflow.com/questions/34450131/…. – Thierry Templier Jan 10 at 8:55
1  
As of Angular 2 RC 0, this is no longer required. – Onur Yıldırım Jul 30 at 12:17
3  
@OnurYıldırım, using rc.4, this import is still required, unless I'm doing something wrong. – Joseph Gabriel Aug 3 at 2:37
4  
Please don't use 'import 'rxjs/Rx';' because it imports everything and rxjs tends to be pretty big. Import operators one by one as you need them. – Drag0 Sep 22 at 13:56
    
Angular 2 with rxjs: 5.0.0-beta.12 here. And I still had to import 'rxjs/add/operator/do'... While we don't have to do this for .map() anymore. But this helped my .do() case, to realize I specifically need to import it. Thank you! One up vote from me :) – MrCroft Sep 25 at 17:56

Just some background... The newly minted Server Communication dev guide (finally) discusses/mentions/explains this:

The RxJS library is quite large. Size matters when we build a production application and deploy it to mobile devices. We should include only those features that we actually need.

Accordingly, Angular exposes a stripped down version of Observable in the rxjs/Observable module, a version that lacks almost all operators including the ones we'd like to use here such as the map method.

It's up to us to add the operators we need. We could add each operator, one-by-one, until we had a custom Observable implementation tuned precisely to our requirements.

So as @Thierry already answered, we can just pull in the operators we need:

import 'rxjs/add/operator/map';
import 'rxjs/operator/delay';
import 'rxjs/operator/mergeMap';
import 'rxjs/operator/switchMap';

Or, if we're lazy we can pull in the full set of operators:

import 'rxjs/Rx';
share|improve this answer
1  
import 'rxjs/Rx'; wow. and all my hair pulling instantly goes away. i can't believe this isn't printed all over the world for Rxjs/Angular2. thanks!!! – JimB Mar 23 at 16:59

Using Observable.subscribe directly should work.

@Injectable()
export class HallService {
    public http:Http;
    public static PATH:string = 'app/backend/'    

    constructor(http:Http) {
        this.http=http;
    }

    getHalls() {
    // ########### No map
           return this.http.get(HallService.PATH + 'hall.json');
    }
}


export class HallListComponent implements OnInit {
    public halls:Hall[];
    / *** /
    ngOnInit() {
        this._service.getHalls()
           .subscribe(halls => this.halls = halls.json()); // <<--
    }
}
share|improve this answer
1  
This isn't a very efficient approach. For instance if there are multiple subscribers they will each have to run map on the data, rather than just doing it once in the service. I think OP had the right approach, just didn't have the right module loaded to use it. – Evan Plaice Jan 25 at 18:17
    
This seemed like the only thing that worked for me! – Ben Liyanage May 15 at 5:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.