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
    

17 Responses to Angular 2 and Ionic 2 Data Services
Part 2: Using REST Services

  1. angular 2 February 5, 2016 at 1:51 am #

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

  2. David February 6, 2016 at 7:42 pm #

    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(…) })

  3. Christophe February 8, 2016 at 10:23 am #

    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.”

  4. kocaeli web tasarım February 8, 2016 at 9:51 pm #

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

  5. David February 15, 2016 at 7:52 pm #

    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

    • David February 16, 2016 at 4:33 pm #

      Found the issue. I included ‘rxjs/Rx';

  6. AngularJS Tutorial February 29, 2016 at 4:29 am #

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

  7. agario March 8, 2016 at 10:05 pm #

    ess than signs.

  8. resim kursu March 20, 2016 at 5:41 am #

    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/

  9. resim kursu March 23, 2016 at 10:46 am #

    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.

  10. Dach April 7, 2016 at 7:18 pm #

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

    • Maruen April 30, 2016 at 3:07 pm #

      Try to build from gulp first ..

  11. Piccaza April 8, 2016 at 8:14 am #

    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; )

  12. George April 16, 2016 at 1:15 pm #

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

  13. Nishanth Kabra May 11, 2016 at 9:13 am #

    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?

  14. propchill May 16, 2016 at 7:58 am #

    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

Trackbacks/Pingbacks

  1. Building Customer-Facing Mobile Apps with Angular 2, Ionic 2, and Salesforce | Christophe Coenraets - February 25, 2016

    […] 1, I shared a first version of the Ionic Realty application using a set of mock data services. In Part 2, I used actual REST services powered by a Node.js back-end. In this article, I share a version of […]

Leave a Reply

css.php