Comment créer votre première application Ionic 4 avec des appels API

Vous venez de remarquer que Ionic 4 est sorti et que vous voulez enfin vous lancer dans le développement d'applications multiplateformes? Eh bien, c'est aujourd'hui votre journée! Nous allons construire votre première application Ionic 4 avec des appels HTTP vers la base de données Open Movie!

Que vous soyez complètement nouveau sur Ionic ou que vous ayez utilisé des versions précédentes, nous passons en revue toutes les bases. Nous expliquerons comment configurer une nouvelle application , le routage et même les appels d'API pour afficher des données asynchrones dans notre application.

Si vous voulez apprendre Ionic encore plus rapidement, vous pouvez également consulter mon Ionic Academy qui a été conçue pour les développeurs comme vous!

Prêt ? Allez !

Configuration de notre application Ionic 4

Si vous êtes nouveau sur Ionic, vous devez vous assurer que le gestionnaire de paquets Node est installé. Si vous avez travaillé avec d'autres technologies Web avant que les chances soient bonnes, vous avez déjà tout ce dont vous avez besoin.

Si vous n'avez pas non plus utilisé Ionic auparavant, vous devez l'installer via npm. Une fois installé, vous êtes enfin prêt à créer votre projet Ionic 4!

Pour configurer un projet vierge, vous pouvez utiliser la CLI Ionic afin que nous nous retrouvions avec un nouveau projet Ionic 4 avec le support Angular ( vous pouvez également utiliser React ou Vue, un meilleur support à venir plus tard cette année ).

Une fois que le projet est créé , nous cd dans le dossier. Nous utilisons la CLI, qui utilise la CLI angulaire sous le capot, pour créer de nouvelles pages pour notre application que nous voulons afficher.

# Install Ionic if you haven't before npm install -g ionic # Create a blank new Ionic 4 app with Angular support ionic start movieApp blank --type=angular cd movieApp # Use the CLI to generate some pages and a service ionic g page pages/movies ionic g page pages/movieDetails ionic g service services/movie

Vous pouvez maintenant ouvrir directement votre application en exécutant la commande suivante dans votre projet:

ionic serve

Cela ouvrira le navigateur avec l'aperçu de votre application qui se rechargera automatiquement une fois que vous aurez changé quoi que ce soit dans votre projet.

En parlant du projet, nous avons un tas de fichiers et de dossiers ici, voyons ce que tout cela signifie. Nous allons nous concentrer sur le dossier src de notre application car nous n'avons pas à nous soucier du reste pour le moment.

App

C'est le dossier dans lequel nous effectuerons toutes les modifications de code qui suivront plus loin dans ce tutoriel. Il contient déjà un dossier d' accueil qui est essentiellement une page comme nous l'avons créé auparavant. J'aime avoir toutes les pages dans leur propre dossier de pages afin que vous puissiez également supprimer le dossier de départ pour le moment.

Le dossier pages contient les vues / pages réelles de notre application, ce qui signifie l'élément que nous verrons à l'écran. Pour le moment, nous avons déjà 2 pages ici, et chaque page que vous créez avec la CLI est livrée avec 4 fichiers:

  • * .module.ts: Le module Angular pour une page. Chaque page est essentiellement son propre module (lié à l'architecture angulaire) avec les importations et le style
  • * .page.html: le balisage HTML d'une page
  • * .page.scss: Le style de la page spécifique (plus d'informations sur le style global plus tard)
  • * .page.spec.ts: Un fichier de test ajouté automatiquement pour votre page. Bon si vous souhaitez mettre en place des tests unitaires automatisés
  • * .page.ts: Le contrôleur d'une page contenant le code Javascript qui gère la fonctionnalité

Le dossier services contient notre service précédemment créé - il s'agit de structurer votre application selon les meilleures pratiques et de séparer les préoccupations entre la vue et les données réelles de votre application. Le service se chargera de gérer les appels API et renverra simplement les données à notre vue plus tard!

Les atouts

Ce dossier contient toutes les images, polices ou tout autre élément dont vous aurez besoin pour votre application plus tard.

Environnements

De temps en temps, votre projet peut avoir un environnement de développement, de préparation et de production avec différents serveurs ciblés par votre application. Le dossier d'environnement permet de configurer les informations pour différents environnements. Nous pouvons plus tard créer notre application Ionic avec un indicateur de ligne de commande et elle prend automatiquement les bonnes valeurs. Très utile!

Thème

Ce dossier contient uniquement le fichier variables.scss qui contient des informations de couleur prédéfinies d'Ionic. Nous pouvons toujours modifier ce fichier et même utiliser un outil comme Ionic Color Generator pour créer notre propre version aromatisée de ce fichier!

En dehors du dossier, nous avons également le fichier global.scss. Ici, nous pouvons écrire quelques SCSS qui seront globalement appliqués à notre application. Nous pouvons également le définir pour une seule page dans leurs propres fichiers de style.

Autres fichiers

Le plus pertinent des autres fichiers pourrait être le fichier index.html car, comme pour tous les autres sites Web, ce fichier marque le point d'entrée de notre application! Pour l'instant, bien que nous n'ayons pas besoin de changer quoi que ce soit ici, commençons maintenant à entrer dans le code réel.

Routage prérequis et appels HTTP

Avec Ionic 4, nous passons d'un concept de routage propriétaire au routeur angulaire standard. Le balisage peut sembler un peu plus difficile au début, mais c'est en fait tout à fait logique.

Pour toutes les connexions à l'intérieur de votre application, vous configurez les informations de routage à l' avance - tout comme vous naviguez sur un site Web!

Dans notre application, nous avons besoin de 2 itinéraires:

  • / movies - Accédez à notre première page qui devrait afficher une liste de films
  • / movies /: id - Nous voulons pouvoir afficher les détails d'un film afin d'ajouter un paramètre : id à l'itinéraire que nous pouvons résoudre dynamiquement

Nous devons également connecter la page correspondante ( plus spécifique : le module de la page) à la route pour qu'Angular sache comment résoudre une route spécifique. Nous fournissons ces informations en utilisant loadChildren qui ne reçoit en fait qu'une chaîne dans le chemin du module .

Cela signifie que nous n'importons pas vraiment un autre module ici, par conséquent, les pages utilisent le chargement paresseux. Cela signifie qu'ils ne seront chargés qu'une fois que nous y naviguerons!

Pour configurer nos informations de routage, ouvrez notre app / app-routing.module.ts et changez-le en:

import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', redirectTo: 'movies', pathMatch: 'full' }, { path: 'movies', loadChildren: './pages/movies/movies.module#MoviesPageModule' }, { path: 'movies/:id', loadChildren: './pages/movie-details/movie-details.module#MovieDetailsPageModule' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }

En faisant ce changement, nous avons également déconnecté la page d'accueil qui était initialement dans le projet (et que vous avez peut-être déjà supprimée à ce stade).

Maintenant, l'application chargera notre page de films comme première page, super! Vous devriez également remarquer ce changement dans votre ionic serveinstance en cours d'exécution .

Conseil: si vous souhaitez avoir une meilleure idée de l'apparence de votre application sur un appareil réel, vous pouvez également l'exécuter ionic labau lieu de la servir, mais vous devez installer le package à l'avance:

# Install the Lab Package npm i @ionic/lab # Run your app with device preview and platform styles ionic lab

Ce package était auparavant fourni avec chaque nouvelle application, mais doit maintenant être installé pour Ionic 4.

/ Fin de la pointe

Nous devons également appliquer une autre modification à notre application car nous voulons effectuer des appels HTTP. Par conséquent, nous devons importer un autre module angulaire pour effectuer ces demandes.

La façon de faire est la même qu'avec Ionic 3. Nous devons simplement ajouter le HttpClientModuleà notre fichier de module principal et l'ajouter au tableau d'importations comme celui-ci dans notre app / app.module.ts :

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 {}

Avant de plonger dans plus de code Ionic 4, nous devons d'abord configurer le service qui alimente notre application et gère toutes les requêtes HTTP que nous voulons appeler plus tard.

Faire des requêtes HTTP

Un service est le même que dans les versions précédentes d'un fournisseur et peut être injecté dans notre contrôleur afin d'appeler ses fonctions.

Pour utiliser la base de données Open Movie, vous devez demander une clé API et l'insérer dans notre service - le processus est gratuit, alors continuez dès maintenant.

Avec l'API, nous pouvons désormais rechercher des chaînes et obtenir des résultats sous forme de films, d'épisodes ou même de jeux. En outre, nous pouvons obtenir des informations détaillées pour un objet spécifique de ces résultats, ce qui constitue un cas d'utilisation parfait pour notre première application Ionic 4!

Notre service n'a besoin que de 2 fonctions:

  • searchData(): Cette fonction recherche les résultats dans un titre et un type de recherche spécifiques - une énumération que nous avons définie à l'avance pour représenter les types que nous pouvons transmettre à l'API en utilisant TypeScript!
  • getDetails(): Cette fonction renvoie les informations détaillées pour un élément spécifique, sera utilisée sur notre page de détails

Both functions will return an Observable which is like a Promise on steroids. No serious, it’s like a stream of events that we can subscribe to. Explaining this concept would take another post. For now, let’s use it and keep in mind that both of our functions are async — they will return the API data not immediately.

Now go ahead and change your services/movie.service.ts to:

import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; // Typescript custom enum for search types (optional) export enum SearchType { all = '', movie = 'movie', series = 'series', episode = 'episode' } @Injectable({ providedIn: 'root' }) export class MovieService { url = '//www.omdbapi.com/'; apiKey = ''; // <-- Enter your own key here! /** * Constructor of the Service with Dependency Injection * @param http The standard Angular HttpClient to make requests */ constructor(private http: HttpClient) { } /** * Get data from the OmdbApi * map the result to return only the results that we need * * @param {string} title Search Term * @param {SearchType} type movie, series, episode or empty * @returns Observable with the search results */ searchData(title: string, type: SearchType): Observable { return this.http.get(`${this.url}?s=${encodeURI(title)}&type=${type}&apikey=${this.apiKey}`).pipe( map(results => results['Search']) ); } /** * Get the detailed information for an ID using the "i" parameter * * @param {string} id imdbID to retrieve information * @returns Observable with detailed information */ getDetails(id) { return this.http.get(`${this.url}?i=${id}&plot=full&apikey=${this.apiKey}`); } }

I’ve also added some documentation to the functions — with a tool like Compodoc you could now create nice documentation!

Alright, now we are finally ready for some more Ionic 4 code!

Searching for Movies

We start our apps functionality with the things that happen in the background and then build the view on top of it.

So right now we need to implement the logic to submit a search term and type to our service and receive the results. Therefore, we inject the service through our constructor so it’s available to the class.

In another function that we call searchChanged() we will now simply call the according function of our service and set the result to a local variable b>results. Our view will later handle the data that comes from the API and display it using this variable.

We also keep 2 more variables for the searchTerm and type inside our class that we pass to the service. We will connect with them from the view as well so we can change them.

Now go ahead with the code for your controller inside the pages/movies/movies.page.ts:

import { MovieService, SearchType } from './../../services/movie.service'; import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; @Component({ selector: 'app-movies', templateUrl: './movies.page.html', styleUrls: ['./movies.page.scss'], }) export class MoviesPage implements OnInit { results: Observable; searchTerm: string = ''; type: SearchType = SearchType.all; /** * Constructor of our first page * @param movieService The movie Service to get data */ constructor(private movieService: MovieService) { } ngOnInit() { } searchChanged() { // Call our service function which returns an Observable this.results = this.movieService.searchData(this.searchTerm, this.type); } }

Now the view which looks a lot like Ionic 3 code, just a few of the elements changed their names and properties. For everyone new to Ionic in general: Welcome to your first Ionic components!

A page can be separated into 3 areas: Header, content, footer. In our case, we don’t want a footer so we only define the header area with a title and the content with our actual elements for the search.

The first element that affects the search is the ion-searchbar which is a simple input you have seen in many apps before to search for a term.

We always want to call our search functionality when the type or searchTerm changes. We can do this by catching the (ionChange) event of some of our elements.

Below we got a select drop down with options and the according value for the different types that we could pass back to the API.

You should have also noticed the [(ngModel)] syntax through which both elements are connected to our controller properties. If one side changes, the other will automatically get the new value as well (also known as 2-way data binding).

So we got the search in place and now add another list with elements below our previous components.

For the list, we use an iteration over our results variable. Because this variable is an Observable (remember the implementation in our service) we need to add an Angular Pipe “| async” to it. The view subscribes to the Observable and handles the changes accordingly.

We also add the routing directly to this element by using [routerLink]. We construct the path that we want to open when we click on the element. We use the imdbID property of the item so we can resolve the information on our details page later.

Besides that, we create the markup for one item using the Poster which is an image, the title, year and finally also a cool icon at the and based on the type of the item. Yes, those cool icons are already bundled with your app and are called Ionicons!

With all of that in mind change your pages/movies/movies.page.html to:

  My Movie Search      Select Searchtype  All Movie Series Episode      

{{ item.Title }}

{{ item.Year }}

By now you should be able to search for a specific term inside your app and get a list of results — that’s already a big win!

If you are coming form Ionic 3 you might have also noted another new property called slot so here’s some info on that:

Ionic 4 components are built using Stencil (yeah, they actually created that tool as well!) so they are standard web components — you could import them basically everywhere on the web! These components also use the Shadow DOM API and are basically living outside of the scope of your regular DOM elements.

That means also standard styling will sometimes not affect these components like it was possible in previous versions!

In order to get information into these components, we can inject certain parts of HTML into their slots that are defined on these elements. You can see how their implementation looks like on the example of the ion-item we used here.

Presenting Detailed Information

Ok enough of background information, let’s put some more work into the details page of our app. We have implemented a route and we also created a button that passed an ID with that route so the details page will be open, but we need to get access to the ID!

With previous Ionic versions we could easily pass whole objects to new pages, this is now not a best practice anymore. Instead, we pass only small chunks of information (like an ID) with the URL. Otherwise, you would end up with a huge JSON stringified term inside the URL. This isn’t really something we want to have.

To get access to this ID field (that we already defined inside our routing in the beginning) we can use the ActivatedRoute and its properties.

So after we extract the ID from the params we can make another call to our service (that we injected through the constructor again) and get the detailed information for whatever ID we got.

Nothing really new so let’s add the following code to our pages/movie-details/movie-details.page.ts:

import { MovieService } from './../../services/movie.service'; import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-movie-details', templateUrl: './movie-details.page.html', styleUrls: ['./movie-details.page.scss'], }) export class MovieDetailsPage implements OnInit { information = null; /** * Constructor of our details page * @param activatedRoute Information about the route we are on * @param movieService The movie Service to get data */ constructor(private activatedRoute: ActivatedRoute, private movieService: MovieService) { } ngOnInit() { // Get the ID that was passed with the URL let id = this.activatedRoute.snapshot.paramMap.get('id'); // Get the information from the API this.movieService.getDetails(id).subscribe(result => { this.information = result; }); } openWebsite() { window.open(this.information.Website, '_blank'); } }

We also added another function to open a website using the window object and the information from the data of the API that we stored in the local information variable.

Now we just need to create a view based on the JSON information of the API. It always helps to log() out the info you got so you see keys that you can use to display some values.

In our case, we use the Ionic card component and add the image and some items with information and more icons (did I say I really like the Ionicons?).

We also added a button below that card that will be displayed if the result information contains the website key. We just have to add our function to the (click) event of the button in order to hook everything up!

On another note, we also have to add an ion-back-button to the header of that page in order to get a nice little back arrow to our previous movie list page. This was automatically done in v3 but needs to implemented manually as of v4!

Now finish your details view by changing your pages/movie-details/movie-details.page.html to:

     {{ information?.Genre }}       {{ information.Title }}   {{ information.Year }}     {{ information.Plot }}   {{ information.imdbRating }}    {{ information.Director }}    {{ information.Actors }}    Open Website    

If you now take a look at your browser you might notice that the image looks waaaay to big as its taking all the space available. Let’s change this through some good old CSS so open your pages/movie-details/movie-details.page.scss and insert:

.info-img { max-height: 30vh; object-fit: contain; padding: 10px; }

Now our results look a lot more appealing.

We can search, select a movie type, dive into a search result and have a fully functional Ionic 4 app with HTTP calls finished!

Conclusion

While it was a straight forward experience to build our first Ionic 4 app there are so many things we haven’t talked enough about.

UI patterns like Tabs and side menu, CSS variables, responsive layout and PWA to just name a few on the side of Ionic and Angular.

And we haven’t even touched the Cordova side of things to actually build this app into a real native mobile app!

If you want to learn how to develop Ionic 4 apps as fast as possible and get them to the iOS & Android app stores quickly you can join the Ionic Academy today and enjoy expert screencasts, a library of quick wins and a community to support you on your journey!

And of course, I (Simon) am also present inside to answer all your questions all the time

You can also find a video version of this guide below!

Originally published at ionicacademy.com on January 24, 2019.