HTTP Example with Observables • HTTP • Angular 4

  • Pressing a Search button every-time we want to make a search is so 2012, lets change our application so it uses a reactive form and performs a search as we type.
  • We’ve covered reactive forms before so we just need to change our AppComponent to add a search field, like so:

    We also change our component to setup a form model, like so:

    // Need to call subscribe to make it hot!

  • We’ve implemented the  ngOnInit function so we can work with our search control once it’s been linked to the form element.
  • To start with lets use the  operator, like so:

    (1) // Need to call subscribe to make it hot!

  • If we ran the above and looked at the logs, instead of seeing see an array of  printing out we see something that looks like an  , like so:

    One workaround would then be to just try doing two subscribes, like so:

    This is a common problem with so there is a better way, we can use another operator called .

Specialist training and professional code reviews for Angular 1, 2 & JavaScript

@LeoLaneseltd: HTTP Example with Observables • HTTP • Angular 4 via @jawache #JS

Working with Observables does require a different way of thinking about programming, It’s my hope that after this lecture you will have a much better idea of how to solve similar problems with RxJS and observables.

propery.

function return an observable which the AppComponent is going to subscribe to, like so:

import { Observable } from ‘rxjs’ ; . . . search ( term:string ) : Observable < SearchItem [] > { .. }

That’s our intention at least but we need to adjust our search function to make it a reality, a first step would look like so:

search ( term:string ) : Obervable < SearchItem [] > { let apiURL = ` $ { this . apiRoot } ? term = $ { term } & media = music & limit = 20 ` ; return this . http . get ( apiURL ) }

, we just return that instead.

However the above has two problems:

, like so:

search ( term: string ) : Observable < SearchItem [] > { let apiURL = ` $ { this . apiRoot } ? term = $ { term } & media = music & limit = 20 & callback = JSONP_CALLBACK ` ; return this . http . get ( apiURL ) (1) . map ( res => { (2) return res . json (). results . map ( item => { (3) return new SearchItem ( (4) item . trackName , item . artistName , item . trackViewUrl , item . artworkUrl30 , item . artistId ); }); }); }

which it then returns to the caller.

as well.

would be just to subscribe to it and store the results locally, like so:

class AppComponent { private loading: boolean = false ; private results: SearchItem []; constructor ( private itunes:SearchService ) { } doSearch ( term:string ) { this . loading = true ; this . itunes . search ( term ). subscribe ( data => { this . loading = false ; this . results = data (1) }); } }

property.

Running the above application works, we can congratulate ourselves for using Observables with HTTP request, but we can go deeper.

pipe in our template like so:

class AppComponent { private loading: boolean = false ; private results: Observable < SearchItem [] > ; constructor ( private itunes:SearchService ) { } doSearch ( term:string ) { this . loading = true ; this . results = this . itunes . search ( term ); (1) } }

pipe in our template, like so:

< div * ngFor = "let item of results | async" > … < /div>

to add a search field, like so:

We also change our component to setup a form model, like so:

class AppComponent { private loading: boolean = false ; private results: Observable < SearchItem [] > ; private searchField: FormControl ; constructor ( private itunes:SearchService ) { } ngOnInit() { this . searchField = new FormControl (); this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . subscribe (); // Need to call subscribe to make it hot! } doSearch ( term:string ) { this . itunes . search ( term ) } }

private searchField: FormControl ;

[formControl]=”searchField”

import { ReactiveFormsModule , FormControl , FormsModule } from ‘@angular/forms’ ; @ NgModule ({ imports : [ BrowserModule , ReactiveFormsModule , FormsModule , HttpModule , ], declarations : [ AppComponent ], bootstrap : [ AppComponent ], providers : [ SearchService ] })

ngOnInit() { … }

this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . subscribe (); // Need to call subscribe to make it hot!

import ‘rxjs/add/operator/debounceTime’ ; import ‘rxjs/add/operator/distinctUntilChanged’ ;

ngOnInit() { this . searchField = new FormControl (); this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . map ( term => this . itunes . search ( term )) (1) // Need to call subscribe to make it hot! . subscribe ( value => console . log ( value )); }

Observable { _isScalar: false, source: Observable, operator: MapOperator }

ngOnInit() { this . searchField = new FormControl (); this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . map ( term => this . itunes . search ( term )) . subscribe ( value => { (1) value . subscribe ( other => console . log ( other ) ) (2) }); }

ngOnInit() { this . searchField = new FormControl (); this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . switchMap ( term => this . itunes . search ( term )) . subscribe ( value => console . log ( value )); }

ngOnInit() { this . searchField = new FormControl (); this . results = this . searchField . valueChanges (1) . debounceTime ( 400 ) . distinctUntilChanged () . switchMap ( term => this . itunes . search ( term )); }

ngOnInit() { this . searchField = new FormControl (); this . results = this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . do ( () => this . loading = true ) . switchMap ( term => this . itunes . search ( term )) . do ( () => this . loading = false ) }

In this lecture we’ve covered, in depth, how to use observables when making HTTP requests.

property could be it’s own observable, how far and how deep to go is up to you. Depending on how comfortable you feel with Observables and how well they match to your use case.

They can be really powerful but at other times they can be a big hindrance with little benefit. In Angular you can use as much or as little reactive programming as you want, it doesn’t prescribe one way or the other.

import { NgModule , Component , Injectable } from ‘@angular/core’ ; import { BrowserModule } from ‘@angular/platform-browser’ ; import { platformBrowserDynamic } from ‘@angular/platform-browser-dynamic’ ; import { HttpModule , Http , Response } from ‘@angular/http’ ; import { ReactiveFormsModule , FormControl , FormsModule } from ‘@angular/forms’ ; import { Observable } from ‘rxjs’ ; import ‘rxjs/add/operator/map’ ; import ‘rxjs/add/operator/debounceTime’ ; import ‘rxjs/add/operator/distinctUntilChanged’ ; import ‘rxjs/add/operator/switchMap’ ; import ‘rxjs/add/operator/do’ ; class SearchItem { constructor ( public track: string , public artist: string , public link: string , public thumbnail: string , public artistId: string ) { } } @ Injectable () export class SearchService { apiRoot: string = ‘https://itunes.apple.com/search’ ; constructor ( private http: Http ) { } search ( term: string ) : Observable < SearchItem [] > { let apiURL = ` $ { this . apiRoot } ? term = $ { term } & media = music & limit = 20 ` ; return this . http . get ( apiURL ) . map ( res => { return res . json (). results . map ( item => { return new SearchItem ( item . trackName , item . artistName , item . trackViewUrl , item . artworkUrl30 , item . artistId ); }); }); } } @ Component ({ selector : ‘app’ , template : ` < form class = "form-inline" > < div class = "form-group" > < input type = "search" class = "form-control" placeholder = "Enter search string" [ formControl ] = "searchField" > < /div> < /form> < div class = "text-center" > < p class = "lead" * ngIf = "loading" > Loading … < /p> < /div> < ul class = "list-group" > < li class = "list-group-item" * ngFor = "let track of results | async" > < img src = "{{track.thumbnail}}" > < a target = "_blank" href = "{{track.link}}" > {{ track . track }} < /a> < /li> < /ul> ` }) class AppComponent { private loading: boolean = false ; private results: Observable < SearchItem [] > ; private searchField: FormControl ; constructor ( private itunes: SearchService ) { } ngOnInit() { this . searchField = new FormControl (); this . results = this . searchField . valueChanges . debounceTime ( 400 ) . distinctUntilChanged () . do ( _ => this . loading = true ) . switchMap ( term => this . itunes . search ( term )) . do ( _ => this . loading = false ) } doSearch ( term: string ) { this . itunes . search ( term ) } } @ NgModule ({ imports : [ BrowserModule , ReactiveFormsModule , FormsModule , HttpModule ], declarations : [ AppComponent ], bootstrap : [ AppComponent ], providers : [ SearchService ] }) class AppModule { } platformBrowserDynamic (). bootstrapModule ( AppModule );

HTTP Example with Observables • HTTP • Angular 4

You might also like More from author

Comments are closed, but trackbacks and pingbacks are open.