Angular2 http subscribe component - http

An angular2 app, try to register an email.
import {Component, Directive, provide, Host} from '#angular/core';
import {NG_VALIDATORS, NgForm} from '#angular/forms';
import {ChangeDetectorRef, ChangeDetectionStrategy} from '#angular/core';
import {ApiService} from '../../services/api.service';
import {actions} from '../../common/actions';
import {EmailValidator} from '../../directives/email-validater.directive';
import * as _ from 'lodash';
import * as Rx from 'rxjs';
#Component({
selector: 'register-step1',
directives: [EmailValidator],
styleUrls: ['app/components/register-step1/register.step1.css'],
templateUrl: 'app/components/register-step1/register.step1.html'
})
export class RegisterStep1 {
email: string;
userType: number;
errorMessage: string;
successMessage: string;
constructor(private _api: ApiService, private ref: ChangeDetectorRef) {
this.successMessage = 'success';
this.errorMessage = 'error';
}
submit() {
var params = {
email: this.email,
type: +this.userType
};
params = {
email: '1#qq.com',
type: 3
};
this._api.query(actions.register_email, params).subscribe({
next: function(data) {
if(data.status) {
console.log("success register");
this.successMessage = "ok ,success";
console.log(this.errorMessage, this.successMessage);
}else{
this.errorMessage = data.message;
console.warn(data.message)
}
},
error: err => console.log(err),
complete: () => console.log('done')
});
}
}
my ApiService is simple:
import {Injectable} from '#angular/core';
import {Http, Headers, RequestOptions} from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
import {AjaxCreationMethod, AjaxObservable} from 'rxjs/observable/dom/AjaxObservable';
import {logError} from '../services/log.service';
import {AuthHttp, AuthConfig, AUTH_PROVIDERS} from 'angular2-jwt';
#Injectable()
export class ApiService {
_jwt_token:string;
constructor(private http:Http) {
}
toParams(paramObj) {
let arr = [];
for(var key in paramObj) {
arr.push(key + '=' + paramObj[key]);
}
return arr.join('&')
}
query(url:string, paramObj:any) {
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
let options = new RequestOptions({headers: headers});
return this.http.post(url, this.toParams(paramObj), options).map(res=>res.json())
}
}
this is my html :
<form #f="ngForm">
usertype<input type="text" name="userType" [(ngModel)]="userType"><br/>
<input type="text" name="email" ngControl="email" email-input required [(ngModel)]="email">
<button [disabled]="!f.form.valid" (click)="submit(f.email, f.userType)">add</button>
</form>
{{f.form.errors}}
<span *ngIf="errorMessage">error message: {{errorMessage}}</span>
<span *ngIf="successMessage">success message: {{successMessage}}</span>
I can success send the api to server and received response, I subscribe an observer to the http response which is a Observable object, inner the next function, I console.log() my successMessage, but i got 'undefined', and when I change the successMessage my html has no change.
It seems like I have lost the scope of my component, then I can't use this keyword

That's because you use the function keyword inside TypeScript. Never do this. Always use the arrow notation () => {}.
You should change your next function to:
next: (data) => {
if(data.status) {
console.log("success register");
this.successMessage = "ok ,success";
console.log(this.errorMessage, this.successMessage);
}else{
this.errorMessage = data.message;
console.warn(data.message)
}

Related

working with FirestoreDocument

I am working with FirestoreDocument and I am trying to retrieving document data.I am getting the post undefined.Below is my code for service and Component
PostService.ts
import { Injectable } from '#angular/core';
import { AngularFirestore,AngularFirestoreCollection,AngularFirestoreDocument} from 'angularfire2/firestore'
import {Post} from './post';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map';
#Injectable()
export class PostService {
postsCollection: AngularFirestoreCollection<Post>
postDoc: AngularFirestoreDocument<Post>
constructor(private afs:AngularFirestore) {
this.postsCollection = this.afs.collection('posts',ref => ref.orderBy('published','desc'));
}
getPosts(){
return this.postsCollection.snapshotChanges().map(actions=>{
return actions.map(a=>{
const data=a.payload.doc.data() as Post
const id=a.payload.doc.id
return {id, ...data}
})
})
}
getPostData(id: string){
this.postDoc=this.afs.doc<Post>(`posts/${id}`)
return this.postDoc.valueChanges()
}
}
PostDetailComponent.ts
import { PostService } from './../post.service';
import { Component, OnInit } from '#angular/core';
import {ActivatedRoute} from '#angular/router';
import {Post} from '../post';
#Component({
selector: 'app-post-detail',
templateUrl: './post-detail.component.html',
styleUrls: ['./post-detail.component.css']
})
export class PostDetailComponent implements OnInit {
post: Post
constructor(
private route:ActivatedRoute,
private postService:PostService
) { }
ngOnInit() {
this.getPost();
console.log(this);
}
getPost(){
const id= this.route.snapshot.paramMap.get('id')
return this.postService.getPostData(id).subscribe(data=>this.post=data)
}
}
PostDetailComponent from console
PostDetailComponent {route: ActivatedRoute, postService: PostService}
post:undefined
postService:PostService {afs: AngularFirestore, postsCollection: AngularFirestoreCollection, postDoc: AngularFirestoreDocument}
route:ActivatedRoute {url: BehaviorSubject, params: BehaviorSubject, queryParams: BehaviorSubject, fragment: BehaviorSubject, data: BehaviorSubject, …}
__proto__:Object
My post from PostDetailComponent is undefined.
The rest of your code looks right, I think it's just that your console.log(this) is in the wrong spot.
ngOnInit() {
this.getPost(); <----- your getPost() function is asynchronous
console.log(this); <----- meaning this console.log runs before you get data from Firebase
so when this runs, posts is still undefined.
If you would console.log(this) *AFTER* you get data
from Firebase, then you should see the values OK.
}
getPost(){
const id= this.route.snapshot.paramMap.get('id')
return this.postService.getPostData(id).subscribe(data=>this.post=data)
^^^^^^^^^^^
ASYNC portion is right here
}
To fix it, move your console.log inside your subscription:
ngOnInit() {
this.getPost();
<--- From here
}
getPost(){
const id= this.route.snapshot.paramMap.get('id')
return this.postService.getPostData(id).subscribe(data=> {
this.post=data;
console.log(this); <--- To here
});
}
EDIT - Additional troubleshooting ref comments below.
getPost(){
const id= this.route.snapshot.paramMap.get('id')
console.log('id from route params is: ' + id); <---- log the *id* too
return this.postService.getPostData(id).subscribe(data=> {
this.post=data;
console.log(data); <--- log *data* instead
});
}
Since angular 6 there were changes on rxjs
// replace import 'rxjs/add/operator/map';
with import { map } from 'rxjs/operators';
Then include .pipe() inside PostService.ts file in getPosts() function
like this:
getPosts() {
return this.postCollection.snapshotChanges().pipe(map(actions => {
return actions.map( a => {
const data = a.payload.doc.data() as Post
const id = a.payload.doc.id
return { id, ...data }
})
})
)
}
Home someone helps, cheers !!!

Angular-Redux Epics

Getting the following error message in console when using the angular-redux library. Also, Redux won't catch or listen for actions after the error occurs. I've searched, including the documentation but nothing points out to fix the error.
Am I missing something?
Error
core.js:1427 ERROR Error: Actions must be plain objects. Use custom middleware for async actions.
at Object.performAction (<anonymous>:3:2312)
at liftAction (<anonymous>:2:27846)
at dispatch (<anonymous>:2:31884)
at eval (createEpicMiddleware.js:67)
at SafeSubscriber.dispatch [as _next] (applyMiddleware.js:35)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:240)
at SafeSubscriber.next (Subscriber.js:187)
at Subscriber._next (Subscriber.js:128)
at Subscriber.next (Subscriber.js:92)
at SwitchMapSubscriber.notifyNext (switchMap.js:127)
Here's code
Component
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { select } from '#angular-redux/store';
import { ScheduleActions } from '../store/actions'
#Component({
selector: 'app-page2',
templateUrl: './page2.component.html',
styleUrls: ['./page2.component.css']
})
export class Page2Component implements OnInit {
#select(['schedule', 'scheduleList']) values: any;
constructor(public actions: ScheduleActions) { }
ngOnInit() {
this.actions.loadSchedule();
}
}
Actions
//schedule-actions.ts
import { Injectable } from '#angular/core';
import { NgRedux } from '#angular-redux/store';
import { Schedule } from '../../model/schedule.model';
#Injectable()
export class ScheduleActions {
static readonly LOAD_SCHEDULE = 'LOAD_SCHEDULE';
static readonly LOAD_SCHEDULE_SUCCESS = 'LOAD_SCHEDULE_SUCCESS';
constructor(private ngRedux: NgRedux<any>){}
loadSchedule(){
this.ngRedux.dispatch({
type: ScheduleActions.LOAD_SCHEDULE
});
}
}
Reducer
//schedule-reducer.ts
import { ScheduleActions } from '../actions';
export interface SCHEDULE_STATE {
scheduleList: any,
scheduleDetail: any
}
const initialState: SCHEDULE_STATE = {
scheduleList: [],
scheduleDetail: {}
}
export const ScheduleReducer = (state: SCHEDULE_STATE = initialState, action): SCHEDULE_STATE => {
switch(action.type){
case ScheduleActions.LOAD_SCHEDULE_SUCCESS:
return {...state, scheduleList: action.payload };
case ScheduleActions.LOAD_SCHEDULE_DETAIL_SUCCESS:
return {...state, scheduleList: action.payload };
case ScheduleActions.CREATE_SCHEDULE_SUCCESS:
return {...state, scheduleDetail: action.payload };
default:
return state;
}
}
Epics
//schedule-epic.ts
import { Injectable } from '#angular/core';
import { ActionsObservable, ofType } from 'redux-observable';
import { ScheduleService } from '../services';
import { ScheduleActions } from '../actions';
import { Observable } from 'rxjs/Observable';
#Injectable()
export class ScheduleEpic {
constructor(private service: ScheduleService,
private actions: ScheduleActions
){}
loadScheduleEpic = (action$: ActionsObservable<any>) => {
return action$.ofType(ScheduleActions.LOAD_SCHEDULE)
.mergeMap(action => {
return this.service.loadSchedule().map(result => {
this.actions.loadScheduleSuccess(result)
})
})
}
}
Service
//schedule-service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Schedule } from '../../model/schedule.model';
#Injectable()
export class ScheduleService {
private API_URL: String = "http://mockserver.io/v2";
constructor(private http: HttpClient){}
loadSchedule(){
return this.http.get(this.API_URL + '/5a6225153100004f2bde7f27').map(res => res)
}
}
That error means you dispatched something that was not an action--in this case, your epic emitted something that wasn't an action.
Thankfully, it's an easy fix! You're just missing a return statement in your map
return this.service.loadSchedule().map(result => {
this.actions.loadScheduleSuccess(result)
})
// change it to this:
return this.service.loadSchedule().map(result => {
return this.actions.loadScheduleSuccess(result)
})

Navigating between same components using Back/Forward browser buttons does not work

Hi I'm having trouble navigating with a browsers back/forward buttons. It only occurs when navigating between routes that share the same component via route parameters.
I have an application that lists lots of animals. Every time I navigate to example.com/animal/cat or example.com/animal/dog, a Http Get request is made to a restful Api which returns the relevant data. If I navigate to /animal/cat then to /animal/dog everything seems ok. The problem starts when I click on the browsers Back Button to go back to /animal/cat. Instead of loading the data for the cat, the URL changes but the data is still listed for the dog. I'm using router 3.0.0-beta.2 with RC4.
heres my animals details.component page:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { ROUTER_DIRECTIVES, ActivatedRoute, Router } from '#angular/router';
import { Response } from '#angular/http';
import { Subscription } from 'rxjs/Rx';
import { DataService } from '../../data.service';
#Component({
moduleId: module.id,
selector: 'animal-details',
templateUrl: 'animal-details.component.html',
styleUrls: ['animal-details.component.css'],
directives:[ROUTER_DIRECTIVES]
})
export class AnimalDetailsComponent implements OnInit, OnDestroy {
constructor(private activatedRoute: ActivatedRoute, private dataService: DataService, private router: Router) {
}
private subscription: Subscription;
animal = {};
link: string;
table = 'animal/';
private url = '?related=family_by_link';
ngOnInit() {
this.subscription = this.activatedRoute.params.subscribe(
(param: any) => this.link = param['link']
);
this.dataService.getData(this.table, this.link, this.url)
.map((response: Response) => response.json())
.subscribe(
(data: any) => {this.animal = data},
err => { console.log('error404') }
);
};
nextData(){
this.dataService.getData(this.table, this.link, this.url)
.map((response: Response) => response.json())
.subscribe(
(data: any) => {this.animal = data},
err => { console.log('error404') }
);
window.scroll(0,0);
};
ngOnDestroy() {
this.subscription.unsubscribe();
};
}
I use the getData() method when navigating between animals on the same component. My AnimalComponentDetails html:
<div class="row">
<div class="col-sm-6 col-md-4 col-lg-3 text-xs-center" *ngFor="let family of animal.family_by_link" (click)="nextData()">
<a [routerLink]="['/animal', family.ani_link]">
<img src="/images/animal/{{family.ani_link}}.png">
<p>{{family.name}}</p>
</a>
</div>
Heres my DataService:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Subscription, Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map'
#Injectable()
export class DataService {
constructor(private dataService: Http) {
}
urlprefix = 'http://123.123.123.123/api/v2/_table/';
api = '&api_key=7201521drgdc71';
getData(table, link, url): Observable<any> {
return this.dataService.get(this.urlprefix + table + link + url +this.api);
}
}
my app.routes:
import { provideRouter } from '#angular/router';
import { AnimalComponent } from './animal/animal.component';
import { AnimalDetailsComponent } from './animal/animal-details/animal-details.component'
{ path: '', component: HomeComponent },
{ path: 'animal', component: AnimalComponent },
{ path: 'animal/:link', component: AnimalDetailsComponent },
{ path: '**', redirectedTo: 'error404', component: Error404Component }
];
export const APP_ROUTES_PROVIDER = [
provideRouter(APP_ROUTES)
];
And my boot:
import { bootstrap } from '#angular/platform-browser-dynamic';
import { enableProdMode } from '#angular/core';
import { AppComponent, environment } from './app/';
import { HTTP_PROVIDERS } from '#angular/http';
import { APP_ROUTES_PROVIDER } from './app/app.routes'
if (environment.production) {
enableProdMode();
}
bootstrap(AppComponent, [APP_ROUTES_PROVIDER, HTTP_PROVIDERS]);
Chrome's Network indicates when I navigate back or forward on the same component between animal/:cat and animal/:dog via browser buttons, no new Http requests are made unless I change to a different component.
This is the last bug I'm down too. Would appreciate any help, thanks!

Data communication in Angular2

I'trying to use the HTTP service in Angular2 and i have some concerns.
I'm taking meteo datas from openweather API and I just want to put it inside a typeScript variable (meteo: {}) and use it as i want in my template.
Here are my .ts files:
meteo.service.ts
import {Injectable} from "angular2/core";
import {Http, Response} from "angular2/http";
import {Observable} from "rxjs/Observable";
import {MeteoComponent} from "../widgets/meteo/meteo.component";
import {Meteo} from "../widgets/meteo/meteo";
#Injectable()
export class MeteoService {
constructor(private http: Http) {}
// Nom de la ville sans accent
private _ville = 'Montreal';
// Initiales du pays
private _country = 'ca';
// Units (metric/imperial)
private _units = 'metric';
// API KEY
private _APPID = 'ewfw54f5646';
// url to get data
private _meteoUrl = 'http://api.openweathermap.org/data/2.5/weather?q='+this._ville+','+this._country+'&units='+this._units+'&APPID='+this._APPID;
getMeteo (): Observable<Meteo> {
return this.http.get(this._meteoUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
if(res.status < 200 || res.status >= 300) {
throw new Error('Bad response status: ' + res.status);
}
let body = res.json();
return body || { };
}
private handleError(error: any) {
let errMsg = error.message || 'server error';
console.error(errMsg);
return Observable.throw(errMsg);
}
}
meteo.component.ts
import {Component, OnInit, OnChanges, AfterContentInit} from "angular2/core";
import {MeteoService} from "../../services/meteo.service";
import {Meteo} from "./meteo";
#Component({
selector: 'meteo',
templateUrl: 'dev/widgets/meteo/meteo.component.html',
providers: [MeteoService]
})
export class MeteoComponent implements OnInit {
errorMessage: string;
meteo: Meteo;
// We inject the service into the constructor
constructor (private _meteoService: MeteoService) {}
// Instantiate data in the ngOnInit function to keep the constructor simple
ngOnInit() {
this.getMeteo();
}
getMeteo() {
this._meteoService.getMeteo()
.subscribe(
data => this.meteo = data,
error => this.errorMessage = <any>error);
}
}
meteo.ts
export class Meteo {
data: {};
}
and meteo.component.html
<span class="meteo">{{meteo | json}}°C</span>
Actually the result is the entire json object:
{
"coord": {
"lon":-73.59,
"lat":45.51
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04d"
}
],
"base":"cmc stations",
"main":{
"temp":3.96,
"pressure":1020,
"humidity":32,
"temp_min":2,
"temp_max":6.67
},
"wind":{
"speed":2.1
},
"clouds":{
"all":75
},
"dt":1461594860,
"sys":{
"type":1,
"id":3829,
"message":0.004,
"country":"CA",
"sunrise":1461577807,
"sunset":1461628497
},
"id":6077243,
"name":"Montreal",
"cod":200
}
And I would like to display just the temp field.
If you have any idea guys it's welcomed!
Thanks a lot.
You could leverage the Elvis operator since your data are loaded asynchronously:
<span class="meteo">{{meteo?.main.temp | json}}°C</span>
Try setting the data on this.meteo.data
getMeteo() {
this._meteoService.getMeteo()
.subscribe(
data => this.meteo.data = data,
error => this.errorMessage = <any>error);
}
and then displaying it with
<span class="meteo">{{meteo.data.main.temp}}°C</span>

How to catch exception correctly from http.request()?

Part of my code:
import {Injectable} from 'angular2/core';
import {Http, Headers, Request, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class myClass {
constructor(protected http: Http) {}
public myMethod() {
let request = new Request({
method: "GET",
url: "http://my_url"
});
return this.http.request(request)
.map(res => res.json())
.catch(this.handleError); // Trouble line.
// Without this line code works perfectly.
}
public handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
myMethod() produces exception in console of browser:
ORIGINAL EXCEPTION: TypeError: this.http.request(...).map(...).catch is not a function
Perhaps you can try adding this in your imports:
import 'rxjs/add/operator/catch';
You can also do:
return this.http.request(request)
.map(res => res.json())
.subscribe(
data => console.log(data),
err => console.log(err),
() => console.log('yay')
);
Per comments:
EXCEPTION: TypeError: Observable_1.Observable.throw is not a function
Similarly, for that, you can use:
import 'rxjs/add/observable/throw';
New service updated to use the HttpClientModule and RxJS v5.5.x:
import { Injectable } from '#angular/core';
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { catchError, tap } from 'rxjs/operators';
import { SomeClassOrInterface} from './interfaces';
import 'rxjs/add/observable/throw';
#Injectable()
export class MyService {
url = 'http://my_url';
constructor(private _http:HttpClient) {}
private handleError(operation: String) {
return (err: any) => {
let errMsg = `error in ${operation}() retrieving ${this.url}`;
console.log(`${errMsg}:`, err)
if(err instanceof HttpErrorResponse) {
// you could extract more info about the error if you want, e.g.:
console.log(`status: ${err.status}, ${err.statusText}`);
// errMsg = ...
}
return Observable.throw(errMsg);
}
}
// public API
public getData() : Observable<SomeClassOrInterface> {
// HttpClient.get() returns the body of the response as an untyped JSON object.
// We specify the type as SomeClassOrInterfaceto get a typed result.
return this._http.get<SomeClassOrInterface>(this.url)
.pipe(
tap(data => console.log('server data:', data)),
catchError(this.handleError('getData'))
);
}
Old service, which uses the deprecated HttpModule:
import {Injectable} from 'angular2/core';
import {Http, Response, Request} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/throw';
//import 'rxjs/Rx'; // use this line if you want to be lazy, otherwise:
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do'; // debug
import 'rxjs/add/operator/catch';
#Injectable()
export class MyService {
constructor(private _http:Http) {}
private _serverError(err: any) {
console.log('sever error:', err); // debug
if(err instanceof Response) {
return Observable.throw(err.json().error || 'backend server error');
// if you're using lite-server, use the following line
// instead of the line above:
//return Observable.throw(err.text() || 'backend server error');
}
return Observable.throw(err || 'backend server error');
}
private _request = new Request({
method: "GET",
// change url to "./data/data.junk" to generate an error
url: "./data/data.json"
});
// public API
public getData() {
return this._http.request(this._request)
// modify file data.json to contain invalid JSON to have .json() raise an error
.map(res => res.json()) // could raise an error if invalid JSON
.do(data => console.log('server data:', data)) // debug
.catch(this._serverError);
}
}
I use .do() (now .tap()) for debugging.
When there is a server error, the body of the Response object I get from the server I'm using (lite-server) contains just text, hence the reason I use err.text() above rather than err.json().error. You may need to adjust that line for your server.
If res.json() raises an error because it could not parse the JSON data, _serverError will not get a Response object, hence the reason for the instanceof check.
In this plunker, change url to ./data/data.junk to generate an error.
Users of either service should have code that can handle the error:
#Component({
selector: 'my-app',
template: '<div>{{data}}</div>
<div>{{errorMsg}}</div>`
})
export class AppComponent {
errorMsg: string;
constructor(private _myService: MyService ) {}
ngOnInit() {
this._myService.getData()
.subscribe(
data => this.data = data,
err => this.errorMsg = <any>err
);
}
}
There are several ways to do this. Both are very simple. Each of the examples works great. You can copy it into your project and test it.
The first method is preferable, the second is a bit outdated, but so far it works too.
1) Solution 1
// File - app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { AppComponent } from './app.component';
import { ProductService } from './product.service';
import { ProductModule } from './product.module';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [ProductService, ProductModule],
bootstrap: [AppComponent]
})
export class AppModule { }
// File - product.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
// Importing rxjs
import 'rxjs/Rx';
import { Observable } from 'rxjs/Rx';
import { catchError, tap } from 'rxjs/operators'; // Important! Be sure to connect operators
// There may be your any object. For example, we will have a product object
import { ProductModule } from './product.module';
#Injectable()
export class ProductService{
// Initialize the properties.
constructor(private http: HttpClient, private product: ProductModule){}
// If there are no errors, then the object will be returned with the product data.
// And if there are errors, we will get into catchError and catch them.
getProducts(): Observable<ProductModule[]>{
const url = 'YOUR URL HERE';
return this.http.get<ProductModule[]>(url).pipe(
tap((data: any) => {
console.log(data);
}),
catchError((err) => {
throw 'Error in source. Details: ' + err; // Use console.log(err) for detail
})
);
}
}
2) Solution 2. It is old way but still works.
// File - app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import { ProductService } from './product.service';
import { ProductModule } from './product.module';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule
],
providers: [ProductService, ProductModule],
bootstrap: [AppComponent]
})
export class AppModule { }
// File - product.service.ts
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
// Importing rxjs
import 'rxjs/Rx';
import { Observable } from 'rxjs/Rx';
#Injectable()
export class ProductService{
// Initialize the properties.
constructor(private http: Http){}
// If there are no errors, then the object will be returned with the product data.
// And if there are errors, we will to into catch section and catch error.
getProducts(){
const url = '';
return this.http.get(url).map(
(response: Response) => {
const data = response.json();
console.log(data);
return data;
}
).catch(
(error: Response) => {
console.log(error);
return Observable.throw(error);
}
);
}
}
The RxJS functions need to be specifically imported. An easy way to do this is to import all of its features with import * as Rx from "rxjs/Rx"
Then make sure to access the Observable class as Rx.Observable.
in the latest version of angular4 use
import { Observable } from 'rxjs/Rx'
it will import all the required things.

Resources