Angular HTTP GET with TypeScript error http.get(...).map is not a function in [null]
AngularRxjsAngular Problem Overview
I have a problem with HTTP in Angular.
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"
]
}
Angular Solutions
Solution 1 - Angular
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. WARNING: This will import all 50+ operators and add them to your application, thus affecting your bundle size and load times.
import 'rxjs/Rx';
See this issue for more details.
Solution 2 - Angular
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. WARNING: this will add all 50+ operators to your app bundle, and will effect load times
import 'rxjs/Rx';
Solution 3 - Angular
From rxjs 5.5 onwards, you can use the pipeable operators
import { map } from 'rxjs/operators';
What is wrong with the import 'rxjs/add/operator/map';
When we use this approach map
operator will be patched to observable.prototype
and becomes a part of this object.
If later on, you decide to remove map
operator from the code that handles the observable stream but fail to remove the corresponding import statement, the code that implements map
remains a part of the Observable.prototype
.
When the bundlers tries to eliminate the unused code (a.k.a. tree shaking
), they may decide to keep the code of the map
operator in the Observable even though it’s not being used in the application.
Solution - Pipeable operators
Pipeable operators are pure functions and do not patch the Observable. You can import operators using the ES6 import syntax import { map } from "rxjs/operators"
and then wrap them into a function pipe()
that takes a variable number of parameters, i.e. chainable operators.
Something like this:
getHalls() {
return this.http.get(HallService.PATH + 'hall.json')
.pipe(
map((res: Response) => res.json())
);
}
Solution 4 - Angular
With Angular 5 the RxJS import is improved.
Instead of
import 'rxjs/add/operator/map';
We can now
import { map } from 'rxjs/operators';
Solution 5 - Angular
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()); // <<--
}
}
Solution 6 - Angular
For Angular versions 5 and above, the updated importing line looks like :
import { map } from 'rxjs/operators';
OR
import { map } from 'rxjs/operators';
Also these versions totally supports Pipable Operators so you can easily use .pipe() and .subscribe().
If you are using Angular version 2, then the following line should work absolutely fine :
import 'rxjs/add/operator/map';
OR
import 'rxjs/add/operators/map';
If you still encounter a problem then you must go with :
import 'rxjs/Rx';
I won't prefer you to use it directly bcoz it boosts the Load time, as it has a large number of operators in it (useful and un-useful ones) which is not a good practice according to the industry norms, so make sure you try using the above mentioned importing lines first, and if that not works then you should go for rxjs/Rx
Solution 7 - Angular
I have a solution of this problem
Install this package:
npm install rxjs@6 rxjs-compat@6 --save
then import this library
import 'rxjs/add/operator/map'
finally restart your ionic project then
ionic serve -l
Solution 8 - Angular
The map you using here, is not the .map()
in javascript, it's Rxjs map function which working on Observables
in Angular...
So in that case you need to import it if you'd like to use map on the result data...
> map(project: function(value: T, index: number): R, thisArg: any): > Observable<R>
Applies a given project function to each value emitted
> by the source Observable, and emits the resulting values as an
> Observable.
So simply import it like this:
import 'rxjs/add/operator/map';
Solution 9 - Angular
Angular version 6 "0.6.8" rxjs version 6 "^6.0.0"
this solution is for :
"@angular-devkit/core": "0.6.8",
"rxjs": "^6.0.0"
as we all know angular is being developed every day so there are lots of changes every day and this solution is for angular 6 and rxjs 6
first to work with http yo should import it from :
after all you have to declare the HttpModule in app.module.ts
import { Http } from '@angular/http';
and you have to add HttpModule to Ngmodule -> imports
imports: [
HttpModule,
BrowserModule,
FormsModule,
RouterModule.forRoot(appRoutes)
],
second to work with map you should first import pipe :
import { pipe } from 'rxjs';
third you need the map function import from :
import { map } from 'rxjs/operators';
you have to use map inside pipe like this exemple :
constructor(public http:Http){ }
getusersGET(){
return this.http.get('http://jsonplaceholder.typicode.com/users').pipe(
map(res => res.json() ) );
}
that works perfectly good luck !
Solution 10 - Angular
Since Http service in angular2 returns an Observable type, From your Angular2 installation directory('node_modules' in my case),We need to import map function of the Observable in your component using http service,as:
import 'rxjs/add/operator/map';
Solution 11 - Angular
Angular 6 - only import 'rxjs/Rx' did the trick for me
Solution 12 - Angular
Just add the line in you file,
import 'rxjs/Rx';
It will import bunch of dependencies.Tested in angular 5
Solution 13 - Angular
True, RxJs has separated its map operator in a separate module and now you need to explicity import it like any other operator.
import rxjs/add/operator/map;
and you will be fine.
Solution 14 - Angular
Global import is safe to go with.
import 'rxjs/Rx';
Solution 15 - Angular
import 'rxjs/add/operator/map';
will resolve your problem
I tested it in angular 5.2.0 and rxjs 5.5.2
Solution 16 - Angular
this is happening because you are using the rxjs and in rxjs function are not static which means you can't call them directly you have to call the methods inside the pipe and import that function from the rxjs library
But if you are using rxjs-compat then you just need to import the rxjs-compat operators
Solution 17 - Angular
I tried below commands and it gets fixed:
npm install rxjs@6 rxjs-compat@6 --save
import 'rxjs/Rx';
Solution 18 - Angular
import { map } from 'rxjs/operators';
this works for me in angular 8
Solution 19 - Angular
Plus what @mlc-mlapis commented, you're mixing lettable operators and the prototype patching method. Use one or the other.
For your case it should be
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
@Injectable()
export class SwPeopleService {
people$ = this.http.get('https://swapi.co/api/people/')
.map((res:any) => res.results);
constructor(private http: HttpClient) {}
}
https://stackblitz.com/edit/angular-http-observables-9nchvz?file=app%2Fsw-people.service.ts