This guide will show you how to write a simple HTTP Rest Angular application. It is also important to point out that we will cover it through the perspective of Angular 7.
 
You will also be able to learn how to use the Master-Detail pattern, including how to work with services.
 
 

Note: If this tutorial was helpful, you need further clarification, something is not working or you have a request for another Ionic post? Furthermore, leave me a comment below if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com. Thanks and have a nice day!
 

Preparations

 
First thing first, let us make sure your Cordova and Ionic 4 work environments are up and ready.
 
We will need these:
 
  • Android Environment (or iOS if you’re working on a MacOS)
  • nodeJS
  • Ionic 4
  • Cordova – Latest one … or, you know what, who cares.
 
If you don’t have a prior Ionic workspace you can find more information here: Ionic 4 | Installation Guide.
 

1. Update Ionic CLI

 
While this is not the top priority make sure you have the latest NodeJS version, sometimes you will not be able to update to the latest version of Cordova and Ionic, above all if you were working with older Ionic versions.
 
If your development environment is up and running, just make sure it’s up to date; older versions may not work with this tutorial:
 
npm install -g ionic cordova
 
or to do a simple update:
 
npm update -g ionic cordova
 
 

2. Create A New Project

 
ionic start IonicHTTPRestExample blank
cd IonicHTTPRestExample
 
–type=ionic-angular is an important parameter as it will tell Ionic CLI to generate a blank Angular based project. This is related to Ionic 4 been platform agnostic (if you prefer ReactJS over Angular man you’re in the wrong place).
 
If you’re an impatient type you can find a working example at the end of this article if; just follow the provided README.md instructions. Jump to the working example here.
 
Warning: As some of you don't have a prior Ionic CLI experience, from this point and on, every time I tell you to execute something, do that inside provided example project folder.
 

3. Add Required Platform

 
Add Android platform:
 
ionic cordova platform add android
 
For Apple master race:
 
ionic cordova platform add ios
 
Or, if you’re a dummy like me (hashtag #dummywhome), you can also use a browser as a platform as this example do not require any mobile-based plugin or resource.
 
ionic cordova platform add browser
 

Introduction

 
For my impatient readers, I will provide you working code examples in advance. In this specific example, we are using one page and one service. Page based function is calling a service based REST function.
 

List page

 
this.movieService.searchMovies(event.target.value).subscribe((res) => {
    this.movies = res;
});
 

Movie service

 
searchMovies(movieName: string) {
    return this.http.get<any>(`${this.apiURL}` + encodeURI(movieName) + `&${this.apiKey}`).pipe(
        map(model => {
            return model.results;
        })
    );
}
 
Continue reading if you require explanations.
 

Code Examples

 
For this article, we will create a simple movie searching application. You will be able to see how Master-Detail pattern pages look like and how to work with Angular HTTP module.
 
To make our life easier we will generate all required pages, classes, and services. This way we do not need to connect or invoke them manually.
 
ionic g page pages/list
ionic g page pages/info
ionic g service services/movie-service
 
Before we can start doing REST calls we need to create a service that will do it for us. For this purpose, we will use a previously created injectable service called movie-service.
 
It looks like this:
 
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Movies } from '../services/movies';

@Injectable({
  providedIn: 'root'
})
export class MovieServiceService {
 
	apiURL: string = 'http://api.themoviedb.org/3/search/movie?query=&query=';
	apiKey: string = 'api_key=5fbddf6b517048e25bc3ac1bbeafb919';
	movies: any = [];

	constructor(private http: HttpClient) { 

	}

	searchMovies(movieName: string) {
		return this.http.get<any>(`${this.apiURL}` + encodeURI(movieName) + `&${this.apiKey}`).pipe(
    		map(model => {
    				this.movies = model.results;
		      		return model.results;
    			}
    		)
    	);	
	}

	getMovieFromCache(id: string) {
		let cachedMovie = null;

	    this.movies.forEach(movie => {
			if (movie.id == id) {
				cachedMovie = movie;
	      	}
	    });

	    console.log(cachedMovie);

	    return cachedMovie;
	}
}
 
As you can see, it is just a simple class without a visible view component.
 
Let us go deeper.
 
As with any other Angular class, the first thing we need to do is import necessary components:
 
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Movies } from '../services/movies';
 
  • The Injectable decorator gives as an ability to use dependency injection application design pattern; which is one of cornerstones of Angular framework.
  • The HttpClient is service that provides a fairly straightforward way of handling requests. Just remember Angular1 $http but with one major difference. HTTP calls in Angular 7 will return observables where Angular1 request will return promises.
  • The RxJs in 'rxjs/operators' stands for Reactive Extensions for JavaScript. It’s a set of libraries which enables us to compose asynchronous/event-based programs using observable collections. And if we want to be more specific about a map operator used here, it’s used, so to speak, to transform a collection of items into a collection of different items.
 
Inject Http service into MovieService class constructor like this:
 
constructor(private http: HttpClient) {

}
 
This way, http will be available to the rest of the class.
 
This is how we can execute HTTP request and get a readable request:
 
return (this.http.get < any > (`${this.apiURL}` + encodeURI(movieName) + `&${this.apiKey}`).pipe(map(model => {
    this.movies = model.results;
    return model.results;
})));
 
Next, we need to include our new service into app.module.ts. Technically, we can also do this on a class level, but that will create a big problem. If each class creates a separate instance we will not be able to share data among them. So be careful.
 
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
 
Let’s take a look at how we can use this service in the List page:
 
import { MovieServiceService } from '../../services/movie-service.service';
 
Include this service into ListPage class constructor:
 
constructor(private movieService: MovieServiceService, private router: Router) {
 
As we want to search movies, we will trigger a REST call on input box input event:
 
<ion-input type="text" (input)="searchForMovie($event, searchKey)"></ion-input>
 
Each time we write a letter it will trigger a REST call to the international movie database. After we enter the third letter, IMDB will send us our first response object:
 
if (event.target.value.length > 2) {
    this.movieService.searchMovies(event.target.value).subscribe(res => {
        this.movies = res;
    });
}
 
Continue to the next page