Http in Ionic 2

Using Http to Fetch Remote Data from a Server in Ionic 2 & 3



·

Although some mobile applications are completely self contained (like calculators, soundboards, flashlight apps), many applications rely on pulling in data from an external source to function. Facebook has to pull in data for news feeds, Instagram the latest photos, weather apps the latest weather forecasts and so on.

You may have seen my recent blog post on how I released an Ionic 2 app on the app store, which required pulling in remote data. In this tutorial I’m going to show you how I did that, and how you can use the Http service to pull data into your own applications.

Before we Get Started

Last updated for Ionic 3.0.0

Before you go through this tutorial, you should have at least a basic understanding of Ionic 2 concepts. You must also already have Ionic 2 set up on your machine.

If you’re not familiar with Ionic 2 already, I’d recommend reading my Ionic 2 Beginners Guide first to get up and running and understand the basic concepts. If you want a much more detailed guide for learning Ionic 2, then take a look at Building Mobile Apps with Ionic 2.

1. Generate a New Application

Let’s start by generating a new Ionic 2 application by running the following command:

ionic start ionic2-http blank --v2

Since we will be using the Http service in this tutorial, we will need to import the HttpModule in our app.module.ts file.

Modify src/app/app.module.ts to reflect the following:

import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    HttpModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

2. Create a List

Before we pull in some data to display in the application, we’re going to set up a list with an empty data source. As is usually the case when we are implementing a feature in Ionic 2, we will need to take care of two main things:

  1. The class definition for the component which will hold (and eventually fetch) the data
  2. The template file that will control what is displayed to the user

Since the blank application template we used to generate our application already contains a home component, we will make use of that for this tutorial.

Modify scr/pages/home/home.ts to reflect the following:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  posts: any;

  constructor(public navCtrl: NavController) {

  }
}

We haven’t really done much at all here, all we’ve done is set up an empty member variable called posts. Eventually, we will fill this with data that we pull in from a remote server, but for now, we are just defining it to prevent the application from complaining when we reference it in the template. Speaking of which…

Modify src/pages/home/home.html to reflect the following:

<ion-header>
  <ion-navbar>
    <ion-title>Home Page</ion-title>
  </ion-navbar>
</ion-header>

<ion-content>
  <ion-list>
    <ion-item *ngFor="let post of posts">
      <img [src]="post.data.url" />
    </ion-item>
  </ion-list>
</ion-content>

Now we’re creating a list, and we are creating an item for each of the posts we have in our posts variable (which is none right now). Inside of the ngFor we are creating an image with a src of post.data.url. When we do eventually pull in some data, this will reference the url of a particular post.

The reason we are using [src] and not src is so that our application knows to evaluate post.data.url as an expression, not use it literally as the source. If we were to just use src it would set the source of the image as post.data.url rather than whatever that evaluates to, which would be something like http://blahblah.com/myimage.gif. This is similar to using double braces likes {{this}} to evaluate an expression.

If you take a look at the application now using the ionic serve command, you won’t see a whole lot. So let’s change that.

3. Fetch Data Using the Reddit API

We’re going to be pulling in some data into the application now by using the reddit API. There’s a lot of cool things you could do with the reddit API, but the reason I wanted to use it for this tutorial is because they provide a very easy to access JSON feed (which is a great format for pulling data into your Ionic applications).

You can create a JSON feed of posts from subreddits simply by visiting a URL in the following format:

https://www.reddit.com/r/gifs/top/.json?limit=10&sort=hot

If you click on that link, you will see a JSON feed containing 10 submissions from the gifs subreddit, sorted by the hot filter. If you’re not familiar with JSON, I would recommend reading up on it here – but essentially it stands for JavaScript Object Notation and is a great way to transmit data because it is very readable to humans, and is also easily parsed by computers. If you’ve ever created a JavaScript object like this:

var myObject = {
    name: 'bob',
    age: '43',
    hair: 'purple'
};

then you should be able to read a JSON feed pretty easily once you tidy it up a little. But how do we get it into our Ionic 2 application?

The answer is to use the Http service which is provided by Angular 2, and allows you to make HTTP requests. If you’re not familiar with what a HTTP request is you can read about it here, but basically every time your browser tries to load anything (a document, image, a file etc.) it sends a HTTP request to do that. The Http service allows us to send off our own requests to retrieve data.

Modify src/pages/home/home.ts to reflect the following

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  posts: any;

  constructor(public navCtrl: NavController, public http: Http) {

    this.http.get('https://www.reddit.com/r/gifs/new/.json?limit=10').map(res => res.json()).subscribe(data => {
        this.posts = data.data.children;
    });

  }
}

We’ve added a couple of imports here, namely Http and the map operator. Http is imported for obvious reasons, but the map import looks a little funky and out of place. The reason we need this is because of the map function we are calling when we use http.get (which I will explain shortly) – in earlier versions of Angular 2 this was included by default so you wouldn’t have to worry about importing it, but anything from the rxjs library seems to need to be manually imported now. This may change in the future, it may not, but for now you’ll just need to remember to add that import when using the map operator.

In order to use Http we need to pass a reference to it through our constructor. We use the static get parameters function to inject the Http service into our constructor. We then assign it to this.http so that we can easily use it anywhere within this class.

Then comes the tricky bit – we use get to retrieve the JSON data from the URL and then assign the data we want to this.posts which is simple enough, but what’s with all that crazy syntax… map, subscribe, fat arrows?

The reason for this new syntax is because Angular 2 is moving towards using Observables, which is provided by the RxJS (Reactive Extensions library. For a bit of a primer on RxJS, check out this video and this video from egghead.io.

So to step through what happens here: http.get returns the result of the request in the form of an Observable, map converts the result into a JSON decoded version of the result, and subscribe allows us to access the data that is returned. In this case we are only handling the success case, but by using subscribe we will also be notified if an error occurs and we can handle that as well like this:

.subscribe(
    data => {
        this.posts = data.data.children;
    },
    err => {
        console.log("Oops!");
    }
);

If you run ionic serve now you should see something like this:

Screenshot 2016-01-06 23.15.05

Keep in mind that we are assuming that the results returned from reddit will link through to an image, so this will work for subreddits like gifs or others that predominantly contain images, but the application wouldn’t be able to handle other types of posts (as you can see by the broken images above).

IMPORTANT: Remember, Http requests are asynchronous. This means that your code will continue executing whilst the data is being fetched, which could take anywhere from a few milliseconds, to 10 seconds, to never. So it’s important that your application is designed to deal with this. To give you an example, if you were to run the following code:

    this.posts = null;

    this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=2&sort=hot').map(res => res.json()).subscribe(data => {
        this.posts = data.data.children;
    });

    console.log(this.posts);

You would see null output to the console, because the console.log runs immediately after we make the get call, it doesn’t wait for it to finish fetching the data. But if you were to run:

    this.posts = null;

    this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=2&sort=hot').map(res => res.json()).subscribe(data => {
        this.posts = data.data.children;
        console.log(this.posts);
    });

You would see the posts output to the console, because everything inside of the subscribe function will only run once the data has been returned.

4. Pulling in Data From Your Own Server

We know how to pull in data using a JSON feed like the one provided by reddit, but what if you want to pull in your own data? How can you go about setting up your own JSON feed?

Going into the detail of how to do this is a bit beyond what I wanted to achieve with this tutorial, but if you want more information you can check out a previous tutorial I’ve done on loading in map markers from a remote server in Ionic 1. This is a reasonably complex example, but all it comes down to in the end is:

  1. Fetch the data using whatever server side language you prefer
  2. Output that data to the page in JSON format

In the tutorial I linked above I’m using PHP, so I’ll give you a quick example of how you might implement a simple API with PHP.

  1. Create a file called feed.php that is accessible at http://www.mywebsite.com/api/feed.php
  2. Retrieve the data, in this case I’m doing that by querying a MySQL database but the data can come from anywhere:
$mysqli = new mysqli("localhost", "username", "password", "database");
$query = "SELECT * FROM table";
$dbresult = $mysqli->query($query);

while($row = $dbresult->fetch_array(MYSQLI_ASSOC)){

    $data[] = array(
        'id' => $row['id'],
        'name' => $row['name']
    );
}

if($dbresult){
    $result = "{'success':true, 'data':" . json_encode($data) . "}";              
}
else {
    $result = "{'success':false}";
}
  1. Output the JSON encoded data to the browser:
echo($result);
  1. Use http://www.mywebsite.com/api/feed.php in your http.get() call in your application

It’s important to note that you can use whatever language and whatever data storage mechanism you like to do this. Just grab whatever data you need, get it in JSON format, and then output it to the browser.

Summary

This should give you a pretty reasonable overview of how to fetch remote data using Ionic 2 and the Http service. The syntax might be a little tricky to get your head around at first, but once you’ve got this working there’s not really much more you need to know. Your data might get more complex and you might want to perform some fancier operations on it or display it in a different way, but the basic idea will remain the same.

As I mentioned before, this application assumes that the incoming results are links to images. As a bit of a homework task for this tutorial, you could try making some changes so that either the application handles all types of posts, or it ignores any posts that don’t link to images.

What to watch next...

  • guy katz

    slightly OT…
    whats a good way to have pinch zoom functionality on images while using ionic?

  • Simon Lucas

    Hi Josh, nice article. I saw this recent update in the Angular 2 API, do you think we would have to change anything in our apps?

    Angular 2 API Changes
    HTTP Module
    Previously we had to inject HTTP_BINDINGS if we wanted to use the Http service. Now this module has been renamed to HTTP_PROVIDERS.
    Also, Http now has native RxJs support! This means we don’t have to call toRx()on the response of an HTTP request. Http methods return an Observable by default.

    🙂

  • void brain

    An integration of this tutorial with local database in addition would be wonderful

  • Aish

    Great article that explain from basics in few min. It works great. Is
    there a way to get an xml file and convert to json and vice versa in
    ionic 2. Please help.

  • Pingback: Wrzutka | Wiadomości o technologiach IT()

  • Kim Wong

    Nice! but i am getting in terrible about post request in ionic2. Would you issue another article about post request?

  • Thomas Degroot

    Hi Josh, one thing I think is missing is a timeout in case of very poor cell reception. I have going through the docs trying to find the best way to do this. Any thoughts how you would do it.

  • YS

    Hi Josh,

    I undesratand that map().subscribe() is part of http service of angular 2.
    I have another example in which I have JSON brought by azure API (they released a beta plugin).

    How should I register to that API in order to update the UI?

  • Dipak Mahapurkar

    Thanks for your grate tutorials, I am new in ionic v2 i want to put tabs all over my app means on every page, My scenario is I Have side-menu with some page which is different from tabs pages, when select side-menu item then i want to put those tabs on that page also. Also how i use movement.js in my app for date format. Thank for help

  • shash

    XMLHttpRequest cannot load

    https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=599…com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile.

    No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access.

    I’am getting the response from the server..i.c google redirection…but at the same time its giving the error..Any idea..?

  • shash

    XMLHttpRequest cannot load
    https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=599…com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile.
    No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘null’ is therefore not allowed access.
    I’am getting the response from the server..i.c google redirection…but at the same time its giving the error..Any idea.

  • M Argus

    Hello Josh, I got error with the code.

    Error when I want to serve the program, It says
    “SyntaxError: H:/Data/Software Engineer/Ionic 2.0 Beta/RestoSystem/app/pages/page1/page1.js: Unexpected token (24:18) while parsing file: H:DataSoftware EngineerIonic 2.0 BetaRestoSystemapppagespage1page1.js”

    And It’s pointed to
    “constructor(http: Http)” to be specific, it’s pointed to “http: Http”..

    why this is happen ? I have no idea what’s going on because I’m not receive any log at console…

  • Hey everybody, I just updated this tutorial for the latest beta

    • arnon

      where i can find it ?

  • Fernando

    Como se podria enviar una imagen en base64 atravez del metodo http.put

  • Pingback: Integrating Ionic 2 with the Dropbox API – Part 1 | HTML5 Mobile Tutorials | Ionic, Phaser, Sencha Touch & PhoneGap()

  • Hi, thank you so much for a detailed tutorial on ionic,
    I have a query , that initially i created a demoapp only using cordova, it ran, build and emulate without issue, but then i installed ionic, and tried to create project, project created, but gave error in emulate,
    Is it a conflict with gradle, which actually installed by cordova itself

  • Josh this is a great post. I have Ionic 1 and apps in production. If I install Ionic 2 then ionic 1 will be removed or what? Can I use both together?

  • Guymer

    Has anyone been able to implement web and mp4 support? I am able to use source tags but they are not loading the files even though the link in the src is correct.

  • Raam

    Whenever I am trying the same , with ngFor it is showing

    Error: Cannot find a differ supporting object ‘[object Object]’ of type ‘object’. NgFor only supports binding to Iterables such as Arrays.

  • Daniel Archer

    hey bro, noticed a typo. you wrote “Modify page1.ts to reflect the following” when you meant to write “home.ts”. 🙂

  • james

    Hi, I can’t drag the open side menu in ionic 2 on my device. Please help. Best Regards

  • Ramu

    Very nicely explained. Thanks for this great article.

  • Emmanuel Asiedu

    https://uploads.disquscdn.com/images/eb9806cb00ba8c1866fecaa362aee71726fda8366ada8bae0a94abd794e5def4.png https://uploads.disquscdn.com/images/096a3f48fad67666c5c0ca7ad15bec24b01b46440776e1629bb6db7e644b9cb5.png Hey, thanks for the tutorial.
    I have created an api with slim and used ngrok to create a tunnel to my localhost but when i make the http requests, i don’t get anything showing.
    These are the codes:

  • jyo

    While using the https service as mentioned in the above tutorial i am getting an error. Plz help me to solve this
    Runtime Error
    Error in ./MyApp class MyApp – caused by: this.http.get(…).map is not a function

    Typescript Error
    Property ‘map’ does not exist on type ‘Observable’.
    src/pages/home/home.ts
    constructor(public http: Http) {
    this.http.get(‘https://www.reddit.com/r/gifs/new/.json?limit=10’).map(res => res.json()).subscribe(data => {
    this.posts = data.data.children;

  • Pingback: Google()

  • Pingback: remote control vibrator()

  • Pingback: Lia Pleasure O()

  • Pingback: male vacuum pump()

  • Pingback: sex talk()

  • Pingback: rabbit vibrator()

  • Pingback: szybki kredyt()

  • Pingback: buy sell cyprus()

  • Pingback: workout and weight loss apps()

  • Pingback: Download VMCT_V9 Certification Dumps()

  • Pingback: forex signal()

  • Pingback: Advertise Online()

  • Pingback: amazon Customer Reviews()

  • Pingback: Best PS4 Headset()

  • Pingback: microfon spion()

  • Pingback: buy youtube views and likes()

  • Pingback: Headworn microphones()

  • Pingback: persian setar()

  • Pingback: M2020-610 Certification Exam Questions and Answers()

  • Pingback: pc apps free download()

  • Pingback: boom truck for sale nevada()

  • Pingback: top smm panel()

  • Pingback: adult sex toy()

  • Pingback: adam and eve sex toy()

  • Pingback: bondage straps()

  • Pingback: wet wabbit()

  • saadasda

    Hi, I have a question. I want to store some data which I get from json file. I have succeded to read from json and show the values in .html file with {{data.id}}. Now I am trying these codes with “id” variable in my .ts file:
    var id:any;
    this.http.get(‘jsonfile’).map(res => res.json()).subscribe(data => {
    this.mydata = data.object;
    id=this.mydata[0].code; //for example
    console.log(“1.trying”+this.id); //this is shown on console
    });
    console.log(“2.trying”+this.id); //this shows “undefined” for id so I mean I could not store and save the id value.
    How can I do this? Thanks…

  • sachin keche

    I am starter in Ionic while communicating with the http i am getting the following error,

    main.js:3324 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
    main.js:42604 Failed to navigate: No provider for Http!
    (anonymous) @ main.js:42604
    main.js:1364 ERROR Error: Uncaught (in promise): Error: No provider for Http!
    Error
    at g (polyfills.js:3)
    at injectionError (main.js:1511)
    at noProviderError (main.js:1549)
    at ReflectiveInjector_._throwOrNull (main.js:3051)
    at ReflectiveInjector_._getByKeyDefault (main.js:3090)
    at ReflectiveInjector_._getByKey (main.js:3022)
    at ReflectiveInjector_.get (main.js:2891)
    at AppModuleInjector.NgModuleInjector.get (main.js:3856)
    at resolveDep (main.js:11260)
    at createClass (main.js:11120)
    at createDirectiveInstance (main.js:10954)
    at createViewNodes (main.js:12303)
    at createRootView (main.js:12208)
    at callWithDebugContext (main.js:13339)
    at Object.debugCreateRootView [as createRootView] (main.js:12800)
    at g (polyfills.js:3)
    at injectionError (main.js:1511)
    at noProviderError (main.js:1549)
    at ReflectiveInjector_._throwOrNull (main.js:3051)
    at ReflectiveInjector_._getByKeyDefault (main.js:3090)
    at ReflectiveInjector_._getByKey (main.js:3022)
    at ReflectiveInjector_.get (main.js:2891)
    at AppModuleInjector.NgModuleInjector.get (main.js:3856)
    at resolveDep (main.js:11260)
    at createClass (main.js:11120)
    at createDirectiveInstance (main.js:10954)
    at createViewNodes (main.js:12303)
    at createRootView (main.js:12208)
    at callWithDebugContext (main.js:13339)
    at Object.debugCreateRootView [as createRootView] (main.js:12800)
    at g (polyfills.js:3)
    at l (polyfills.js:3)
    at polyfills.js:3
    at t.invokeTask (polyfills.js:3)
    at Object.onInvokeTask (main.js:4415)
    at t.invokeTask (polyfills.js:3)
    at n.runTask (polyfills.js:3)
    at a (polyfills.js:3)

  • Леонид Лялин

    [01:42:00] typescript: src/providers/people-service.ts, line: 23

    Property ‘posts’ does not exist on type ‘PeopleService’.

    L22: .subscribe(data => {

    L23: this.posts = data.results.name;

    L24: });

  • Thanks for the tutorial! Stuck on how to retrieve data that isn’t an image. Could you point me in the right direction? Thanks!

  • Vivek Sinha

    Hi,
    In error block of http call I want to show an alert with refresh button which again call the same function. I am able to show alert & reload data as per console. But component is not receiving that response. How can I do it?

  • Arnold Parge

    YOU ARE GREAT!