Often, we will need to load some data into our applications. One common way to do this is to load a JSON (Javascript Object Notation) string from some source and convert that into a Javascript Object that we can view and manipulate in our application.
In this video tutorial, I walk through how to use the Http service to make a get
request to load some JSON data. We cover how to load JSON data that is accessible through a remote server using a URL, as well as JSON data that is available within the application through a local file.
Here’s the video:
Video Notes
- A
get
request using the Http service returns an Observable. This Observable can be subscribed to, to retrieve the JSON data - We can apply a
map
to the Observable before subscribing to it to modify the response into something more friendly, like returning a standard Javascript Object - The Http service can retrieve data from a remote URL or a local file path
Video Transcript
In this tutorial, I am going to show you how to load some data into your Ionic applications using an HTTP request. In this tutorial, we are going to load some JSON data. If you don’t already know what JSON, it stands for JavaScript Object Notation. It is what we are looking at on the screen right now. It is not specific to Javascript, it is just a data format, but it uses the JavaScript object syntax:
{
"someObject": {
"someProperty": true,
"someOtherProperty": false
}
}
0:35
This following is a JSON string that I have loaded from Reddit. If you look at the URL here, we are just grabbing a JSON feed from the GIF subreddit. This is obviously quite a complicated looking string, but if we just jump into the editor… If you broke this down it would look like a normal Javascript object:
{
"kind": "Listing",
"data": {
"children": [
]
}
}
1:30
This is basic JavaScript style object. If you have worked with Javascript before you would be familiar with this, and that is all the JSON string is. This JSON format is a really popular format to work with because it is so easy to parse in our applications. It is easy for humans to read and create and it is also easy for our program to interpret and create an object that we can use inside of our application.
1:55
We are going to go through 2 scenarios in this tutorial. We are going to load in this Reddit data directly from the URL. We are fetching some data from a remote server, but we are also going to store a local file inside of our application that is also going to be in JSON format. We are going to load that locally.
2:13
The HTTP service can load data from the URL like this but it can also just load in and make an HTTP request locally as well (i.e. from a file stored inside of your application).
2:23
I have already got an application generated to use as an example. What we are going to do is add in a provider that we are going to use to fetch this data. If you haven’t got an application you aren’t already working in, feel free to create one and then run the following generate command.
ionic g provider RedditData
2:54
If we go back into our project now and jump into the source folder and go to providers you can see this reddit-data.ts provider that was created for us. It is really handy using this generate command because it imports the HTTP service from Angular and sets it up in the constructor by default. If you wanted to use the HTTP service somewhere else in your application, just make sure to import that Http (UPDATE: You should now use HttpClient instead) service from the Angular library and also inject it into the constructor.
3:31
You will also notice that we have this second import command here which is loading something from the rxjs library. This is the map operator which is going to allow us to do something with the observable that the HTTP service returns, but we will get into that in just a little bit.
3:49
What I am going to do here is create a function. We are going to make this function load in that data from Reddit using the HTTP service. To do this we are going to make use of the HTTP service we have injected into the constructor.
src/providers/reddit-data.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';
@Injectable()
export class RedditData {
constructor(public http: HttpClient) {
console.log('Hello RedditData Provider');
}
getRemoteData(){
console.log(this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=105sort=hot'));
}
}
4:47
Save that, and since we are going to have to interact with this provider we are going to have to set it up properly in the application as well. I am just going to add it into the app.module.ts file and import that RedditData service.
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { RedditData } from '../providers/reddit-data';
@NgModule({
declarations: [MyApp, HomePage],
imports: [BrowserModule, HttpClientModule, IonicModule.forRoot(MyApp)],
bootstrap: [IonicApp],
entryComponents: [MyApp, HomePage],
providers: [
StatusBar,
SplashScreen,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
RedditData,
],
})
export class AppModule {}
5:17
I am going to ionic serve
the application. Then we are going to just go back into the code and we are going to set that provider up in the home.ts file. I am also going to import the provider in here.
5:55
I am also going to add the ionViewDidLoad
hook which will trigger as soon as the view is loaded and we are going to trigger that getRemoteData
function we are creating from the providers/reddit-data.ts file.
src/app/home/home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { RedditData } from '../../providers/reddit-data';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController, public redditService: RedditData) {
}
ionViewDidLoad(){
this.redditService.getRemoteData();
}
}
6:40
Save that and see what that does. That is working now, the function is getting called now and we can see our function making the HTTP request here which returns the observable. This isn’t what we want – well, it is – but it’s not the final thing that we want. You might expect this to return the data but it doesn’t, it returns an observable.
7:09
If you are unfamiliar with observables, I am not going to describe them in this tutorial but you can learn about Observables here. But, really quickly, it is a thing that we can subscribe to that is going to admit data over time. So, an observable can basically say anything at any point in time, and if we are listening, we can grab whatever the thing is that the observable said. In the case of the HTTP request, the thing that it is saying, that we subscribe to, that we are listening for, is going to be the data. So, our getRemoteData
returns an observable, not the data we want but we can get the data we want from that observable.
7:52
We don’t want to log out the data anymore, what we want is to subscribe to that observable. To do that all we need to do is this:
src/providers/reddit-data.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';
@Injectable()
export class RedditData {
constructor(public http: HttpClient) {
console.log('Hello RedditData Provider');
}
getRemoteData(){
this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=105sort=hot').subscribe(data => {
console.log(data);
};
}
}
8:17
Save that and we will see what happens now. Now we have this response which looks a little bit more like what we want – not exactly what we want – but it is looking a little better.
8:30
We expand the code in the console, we can see that we have a whole bunch of stuff in here. We have some headers, some HTTP status codes which says 200 which means it has worked, and then we have the actual data that we are interested in which is buried in the Response property.
Map Operator
8:48
If you wanted to, you could just grab that out of there but there is a better way to do that, and that is where this map operator is going to come in. This map operator that we are importing from the rxjs, we can use with observables. That is what the rxjs library provides – that is what allows us to use observables, and the map is an operator that we can use on that. It is almost exactly like the map method that you can use in Javascript by default. Again, I am not going to to get into how maps work but you can watch this video to find out more. Essentially, in terms of an array, you can apply map functions to an array to change its elements based on some function. It is the same concept here where we can apply the map operator to an observable and we can change the response in some way.
9:48
Before we subscribe to this observable, we are going to add in a map.
src/providers/reddit-data.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';
@Injectable()
export class RedditData {
constructor(public http: Http) {
console.log('Hello RedditData Provider');
}
getRemoteData(){
this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=105sort=hot').map(res => res.json()).subscribe(data => {
console.log(data);
};
}
}
10:16
Save that and take a look in the browser. You can see now that we have a much more friendly-looking app. If I expand the code in the console now this is exactly the data we want. We have the kind and data properties. We have the kind that is the listing, and the data property that has an object in it which has an array inside of it. If we expand the code we can see that we have that listing value there and if we expand data we can see all of that, we can see the children array and we can see a bunch of objects in there with some more data and then this is each individual post in the GIF subreddit. Now we can start to see things like the permalink and different information about that post. Down further we even have to actual URL to the GIF.
11:12
If I copy and past the GIF URL into the browser we can hopefully see what that is. It is a GILF of some lightning.
11:25
Let’s just go back to the original code now. We have covered how to fetch some remote data using HTTP and this is about all you will really have to do and it is almost always going to be this exact format. You will use the Http service with some URL, you map it into a JSON object, subscribe to that and then do whatever you need to do with that data.
Fetching Local Data
11:51
I also said we were going to fetch some local data as well. You might have some JSON file that you want to load that you are bundling with your application. We are going to create another function in the reddit-data.ts file.
src/providers/reddit-data.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';
@Injectable()
export class RedditData {
constructor(public http: HttpClient) {
console.log('Hello RedditData Provider');
}
getRemoteData(){
this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=105sort=hot').map(res => res.json()).subscribe(data => {
console.log(data);
};
}
getLocalData(){
this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=105sort=hot').map(res => res.json()).subscribe(data => {
console.log(data);
};
}
}
12:14
We are going to come back to this in just a second but first, we are going to have to create a data file for us to use. We can add this to the assets file. Right-click assets and create a new folder and call that data. Inside of data we are going to create a file called redditData.json.
12:45
To save myself from coming up with my own JSON string, I am just going to dump all of this data into this file. You can see it looks a lot nice when it is pasted because we can see some syntax highlighting going on.
13:02
Save that and then jump back into the reddit-data.ts file. All I have to do now is change the getLocalData
URL to this:
src/providers/reddit-data.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/map';
@Injectable()
export class RedditData {
constructor(public http: Http) {
console.log('Hello RedditData Provider');
}
getRemoteData(){
this.http.get('https://www.reddit.com/r/gifs/top/.json?limit=105sort=hot').map(res => res.json()).subscribe(data => {
console.log(data);
};
}
getLocalData(){
this.http.get('assests/data/redditData.json').map(res => res.json()).subscribe(data => {
console.log(data);
};
}
}
13:26
We are supplying that local path now and save that and then modify the DidLoad function in the home.ts file.
src/app/home/home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { RedditData } from '../../providers/reddit-data';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController, public redditService: RedditData) {
}
ionViewDidLoad(){
this.redditService.getLocalData();
}
}
13:38
Hopefully, we should see the exact same thing. We have the same object, with the same everything, except now it is coming from the local data. You can see it is coming from line 29 so if we jump into the code you can see that is where it is getting logged out. So, it is now coming from the LocalData function, not the RemoteData function.
14:04
When you first come across this syntax, observables and subscribing, it can look pretty daunting and confusing but the process for pulling some JSON data into your application is pretty simple.
14:17
I hope you enjoyed this tutorial and I will see you in the next one.