Monday, February 13, 2017

Angular 2 HTTP Requests with Observables



We use an http client to talk to a remote server.
  • The Angular Http client communicates with the server using a familiar HTTP request/response protocol. The Http client is one of a family of services in the Angular HTTP library.
  • Before you can use the Http client, you need to register it as a service provider with the dependency injection system.
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';
import { HttpModule, JsonpModule } from '@angular/http';

import { AppComponent } from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    JsonpModule
  ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule {
}


We need to use http and observable to handle asynchronous calls.

Observable

  • Observable are similar to promises but with major difference that make them better.
  • Observables is an ES7 feature which means you need to make use of an external library to use it today. RxJS is a good one.

Observable Operators

  •  RxJS also provides Observable operators which you can use to manipulate the data being emitted. Some of these operators are:
    • Map
    • Filter
    • Take
    • Skip
    • Debounce
  • When we use observable we simply replace "then with subscribe".The value function is called for each value the observable emits
  • Process each value as it is emitted
Note: Observable sequences are called as marble diagram

MAP operator
  • Allows us transform incoming data
  • The argument to the map is an arrow function, that says to take each data item and transform to 10 times its value.
          map(x => 10* x )
         When we receive 1 its is mapped to 10 and when we receive 2 it is mapped to 20
  • To use the map operator we need to load it using import statement
     

Promise vs Observable


We need @Injectable decorator while using http


import {Injectable } from '@angular/core';
//used for http and response
import { Http, Response } from '@angular/http';
//used for observable
import { Observable } from 'rxjs/Observable';
// used for do operator
import 'rxjs/add/operator/do';
// used for catch operator
import 'rxjs/add/operator/catch';
//Used for map operator. This loads the operator without importing
import 'rxjs/add/operator/map';

import { ICompany } from './company';

@Injectable()
export class CompanyService{
    //we need to change it to the actual web server
    private _companyUrl='http://localhost:5000/api/companys'
    //constructor
    constructor(private _http:Http){}

    getCompanies(): Observable<ICompany[]> {
        return this._http.get(this._companyUrl)
                       // when we get the response we use the map operator
                        .map((response: Response) => <ICompany[]> response.json())
                        // allows us to peak the data returned from the server without 
                        disrupting the flow
                        .do(data => console.log('All: ' +  JSON.stringify(data)))
                        .catch(this.handleError);
    }
    //method to handle error
    private handleError(error: Response) {
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }           

}

Note:

Further observable take advantage of generics to define the type of data it is observing in the observable sequence


    getCompanies(): Observable<ICompany[]> {
        return this._http.get(this._companyUrl)

  • We need to translate the response to array of objects --> We can do that using the map operator

Subscribe to the observable

This companyService need to be registered in app.Module and would be available for all the components

// import angular core module
import {Component,OnInit} from '@angular/core';
// import the interface
import {ICompany} from './company'
// import the service
import {CompanyService} from './company.service'
@Component({
 templateUrl:'app/company/company-list.component.html',
 providers:[CompanyService]
})
export class CompanyListComponent implements OnInit{
    companyId:number;
    companyName:string;
    location:string;
    companies:ICompany[];
    errorMessage:string;
    //Fetch the data in the constructor
    constructor(private _companyService:CompanyService){

    }
    
    ngOnInit():void {
        this._companyService.getCompanies()
        //subscribe to the observable
        .subscribe(companies=>this.companies=companies,
                   error =>this.errorMessage=<any>error);
 
    }
}

Display the data in the html templates

 <tbody>
                    <tr *ngFor='let company of companies | productFilter:listFilter'>
                        <td>{{ company.companyId }}</td>
                        <td>{{ company.companyName | lowercase }}</td>
                        <td>{{ company.location }}</td>
                 </tbody>

Output

No comments:

Post a Comment