Angular 2 and Ionic 2 Data Services
Part 2: Using REST Services

In part 1 of this series, I shared two approaches to create Mock services in Angular 2 / Ionic 2 applications: using a Promise-based or an Observable-based API. In this article, I’ll share a version of the IonicRealty sample application implemented using actual REST services, and I’ll revisit the Observable vs Promise discussion.

The code for the application is available in this GitHub repo, including a Node.js server app that powers the REST services.

Let’s take a look at one of the services of the IonicRealty app. PropertyService provides access to the list of Houses and Condominiums for sale, and is implemented as follows (showing only two REST service calls for brevity):

property-service.js:

import {Injectable} from 'angular2/core';
import {SERVER_URL} from './config';
import {Http, Headers, RequestOptions} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';

let favorites = [],
    propertiesURL = SERVER_URL + '/properties',
    favoritesURL = propertiesURL + '/favorites';

@Injectable()
export class PropertyService {

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

    findAll() {
        return this.http.get(propertiesURL)
            .map(res => res.json())
            .catch(this.handleError);
    }

    favorite(property) {
        let body = JSON.stringify(property);
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        return this.http.post(favoritesURL, body, options)
            .map(res => res.json())
            .catch(this.handleError);
    }

    handleError(error) {
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }

}

Code highlights:

  • We use Angular’s http object to access the REST services.
  • The Angular 2 http object methods (get, post, put, etc.) don’t return Promises: they return Observables from the RxJS library.
  • The Observable.map() function is used to transform the response in a format easily consumable by the observer.
  • import ‘rxjs/Rx’; adds all the operators to Observable (map, catch, etc). Operators could also be added individually.
  • When “posting” to the server (like in the favorite function), we need to set the Content-Type header to application/json (the content type expected by our REST service).

Pages and components can then call findAll() and subscribe to process the result as in the ngOnInit function below:

property-list.js:

import {OnInit} from 'angular2/core';
import {Page, NavController, NavParams} from 'ionic/ionic';
import {PropertyDetailsPage} from '../property-details/property-details';
import {PropertyService} from '../../services/property-service';

@Page({
    templateUrl: 'build/pages/property-list/property-list.html'
})
export class PropertyListPage {

    constructor(nav:NavController, navParams:NavParams, propertyService:PropertyService) {
        this.nav = nav;
        this.propertyService = propertyService;
        this.selectedItem = navParams.get('item');
    }

    ngOnInit() {
        this.propertyService.findAll().subscribe(
            data => this.properties = data
        );
    }

    itemTapped(event, property) {
        this.nav.push(PropertyDetailsPage, {
            property: property
        });
    }

}

Promises vs Observables

As discussed in part 1, you could also create your Angular services with a Promise-based API instead of an Observable-based API. To do that, you’d simply use the Observable.toPromise() function to turn Observables into Promises after calling an http object method.

For example, the findAll() function could be rewritten as follows:

property-service.js:

findAll() {
   return this.http.get(propertiesURL)
       .toPromise()
       .then(res => res.json(), err => console.log(err));
}

In PropertyListPage, you could then call findAll() using the traditional Promise syntax:

property-list.js:

ngOnInit() {
   this.propertyService.findAll().then(data => this.properties = data);
}
Keep in mind that Observables are the new standard for the http object in Angular 2 and have advantages over Promises. Check out this video for a quick comparison. To quote the Angular doc: “Don’t rush to promises until you’ve given observables a chance.”

Deploying and Running on Heroku

The easiest way to deploy and run the application (client and server) is to click Deploy to Heroku button below.

  1. Make sure you are logged in to Heroku (sign up for a free account if you don’t already have one)
  2. Click the Deploy to Heroku button below to deploy the application on Heroku

    Deploy
  3. When the deployment process completes, click the View button at the bottom of the screen

Your own instance of the application is automatically deployed.

Deploying and Running Locally

To deploy and run the application (client and server) locally:

  1. Install the the latest beta version of the Ionic CLI:
    npm install -g ionic@beta
    

    or

    sudo npm install -g ionic@beta
    
  2. Clone this repository
  3. Navigate to the ionic2-realty-rest directory
  4. Install the dependencies
    npm install
    
  5. Start the server
    node server
    
  6. Open another command prompt and type the following command to build the app and start it in the browser:
    ionic serve
    
  • angular 2

    Join angular 2 group and get new resources every day https://www.linkedin.com/groups/8434339

  • David

    Am I wrong if I say the ngOnInit arrives after the typescript constructor?

    If so, if you need “properties” in the PropertyListPage constructor, how you will get it?

    For now, I am using a promise in the Service but I am sure there is another way, right?

    return new Promise((resolve, reject) => { this.http.get(…) })

  • ngOnInit is a lifecycle hook that Angular calls when it instantiates the page. You could get the properties in the constructor, but that’s not considered a best practice. Per Angular’s doc: “Components are easier to test and debug when their constructors are simple and all real work (especially calling a remote server) is handled in a separate method.”

  • I found this article useful. Thank you so much. Your labor is very nice

  • Hi again!

    I wanted to do something similar to you, but wanted to use the forkJoin function. I called functions that return the http.get. For some reason, I got the below:

    EXCEPTION: TypeError: Observable_1.Observable.forkJoin is not a function in [null]
    ORIGINAL EXCEPTION: TypeError: Observable_1.Observable.forkJoin is not a function
    TypeError: Observable_1.Observable.forkJoin is not a function
    at DashboardPage.ngOnInit (dashboard.ts:126)
    at AbstractChangeDetector.ChangeDetector_HostDashboardPage_0.detectChangesInRecordsInternal (viewFactory_HostDashboardPage:21)
    at AbstractChangeDetector.detectChangesInRecords (abstract_change_detector.js:105)
    at AbstractChangeDetector.runDetectChanges (abstract_change_detector.js:82)
    at AbstractChangeDetector._detectChangesContentChildren (abstract_change_detector.js:182)
    at AbstractChangeDetector.runDetectChanges (abstract_change_detector.js:83)
    at AbstractChangeDetector._detectChangesInViewChildren (abstract_change_detector.js:189)
    at AbstractChangeDetector.runDetectChanges (abstract_change_detector.js:86)
    at AbstractChangeDetector._detectChangesInViewChildren (abstract_change_detector.js:189)
    at AbstractChangeDetector.runDetectChanges (abstract_change_detector.js:86)

    The call looks like:

    ngOnInit() {
    Observable.forkJoin(
    this._unitService.retrieveUnitsData(),
    this._ctrlService.retrieveCtrlData(),
    this._groupService.retrieveGroupsData()
    ).subscribe(
    data => {
    this._unitsList = data[0];
    this._ctrlList = data[1];
    this._groupList = data[2];
    }
    );
    }

    Do you see something that I should correct?

    Thanks

    • Found the issue. I included ‘rxjs/Rx’;

  • Pingback: Building Customer-Facing Mobile Apps with Angular 2, Ionic 2, and Salesforce | Christophe Coenraets()

  • Why exactly do we use angular? (not that its bad ir anything, just want to know the reasoning :) )

  • ess than signs.

  • Türkiyenin en nitelikli kurumu olan bakırköy resim kursu ile sizi gelecek adına güzel sanatlara hazırlık alanına hazırlamaktadır. Yüzlerce mezun ve nitelikli öğrenci bizlerle mezun oldu sizide ofisimize bekleriz en kaliteli eğitimi ayağınıza kadar getiirdik.

    http://ruyaavcisi.com/

  • Eğitim almış yüzlerce mezunumuz sektörün en kaliteli resimlerini çizmektedirler. Eğitimini almak istediğiniz çizim tekniklerini Ubeyt ÇAĞATAY eşliğinde vermekteyiz. Bakırköy resim kursu ile sizlerleyiz. Güzel sanatlara hazırlıkta bir numaralı adresiniz olmaya devam etmekteyiz.
    Avcılar ve Esenyurt şubeleri ile sizlere bir adım daha yakınız.

  • Dach

    Why does editing the app/app.js file have no effect?
    But editing the app-bundle does?

    • Try to build from gulp first ..

  • Piccaza

    Hi Christophe,

    Many Many Thanks fro the tutorial.

    while using for facebook graph api getting, TypeError: this.http.get(…).map is not a function.

    I am trying following api : (“https://graph.facebook.com/me?fields=email,name,id&access_token=”+access_token; )

  • George

    Don’t you need to implements OnInit in your consumer class? Propertylistpage

  • Hi author, am writing an ionic 2 app and follow your posts on that lines. I just need some light on the following.
    I have a service and i want to NavController for navigation but not able to do it and getting “NO provider error.”
    Do you have any posts written for that? Any pointers?

  • The mid-lodging fragment of Bengaluru caters principally to the IT and ITES representatives. The Bengaluru extends that fall into this classification are evaluated by their physical and social base, the vicinity of municipal, instructive and medicinal offices, nature of neighborhood and if there should arise an occurrence of working people, the closeness to work environment. Ranges, for example, Whitefield, Electronic City, ORR IT Corridor and others in North Bengaluru have seen an ascent in mid-wage portion ventures. Real Estate Property In bengaluru

  • Michael Olukoya

    This is awesome, thanks!

css.php