---
title: Développer une application Angular
tags: frontend, support, angular
robots: noindex, nofollow
author: Julien Noyer
---
# Développer une application Angular
*Platform for building mobile and desktop web applications*

> © [Julien Noyer](https://www.linkedin.com/in/julien-n-21219b28/) - All rights reserved for educational purposes only
---
## Introduction
[Angular](https://angular.io) (communément appelé Angular 2+ ou Angular v2 et plus) est un cadriciel (framework) côté client, open source, basé sur [TypeScript](https://www.typescriptlang.org), et co-dirigé par l'équipe du projet « Angular » à Google et par une communauté de particuliers et de sociétés. Angular est une réécriture complète de AngularJS, cadriciel construit par la même équipe.
## Environement de travail
La méthode la plus communément utilisée pour développer des applications avec Angular est celle qui consiste à utiliser une suite de [CLI](https://fr.wikipedia.org/wiki/Interface_en_ligne_de_commande) nommée [AngularCLI](https://cli.angular.io) qu'il est possible d'installer avec la commande suivante :
```
sudo npm install -g @angular/cli
```
> Le préfixe `sudo` obligatoire dans certains cas pour installer le module en global.
Les instructions qui suivents dans ce documents sont baséee sur l'utilisation de [AngularCLI](https://cli.angular.io) pour simplifier la démonstration des notions qu'il aborde.
---
# Créer un projet Angular
*Utilisation de base de l'interface d'invite de commande d'Angular*

## Démarrer un nouveau projet Angular
Pour bien débuter le développement d'une application avec [Angular](https://angular.io) il est important de respecter une structure et de correctement organiser les différents [composants](https://angular.io/guide/architecture-components) qui seront utilisés dans l'application. Il est donc important de sélectionner un dossier spécifique sur la machine locale dans laquelle sera développée l'application [Angular](https://angular.io).
Nous sélectionnons le dossier contenant nos différrentes projets pour y créér notre application [Angular](https://angular.io) avec la commande suivante :
```
ng new ANGapp
```
Au lancemant de cette commande une prémière question nous est posée, il nous est demandé si nous souhaitons ou nous ajouter un [routeur](https://angular.io/guide/router) :
```
? Would you like to add Angular routing? (y/N)
```
Nous n'ajoutons pas de [routeur](https://angular.io/guide/router) et nous passons à l'étape suivante qui nous demande de sélectionner le format de style que nous souhaitons utilisé :
```
? Which stylesheet format would you like to use? (Use arrow keys)
```
Nous sélectionnons CSS puis nous validons notre choix. Suite à cette dernière commande, tous les packages nécessaires à l'utilisation de [Angular](https://angular.io) sont installés, nous nous plaçons ensuite dans le dossier qui vient d'être créé :
```
cd ANGapp
```
---
# Gestion des routes de l'application
*Mise en place d'une structure de base d'application Web*

## Associer des composants aux endpoints
Contrrairement à des routes serveur, celles utilisées dans Angular n’ont pas pour but de correspondre à des requêtes HTTP mais plutôt d’utiliser les endpoints des URL, pour afficher dans le DOM un composant spécifique. Dans la mesure ou une application Angular s’affiche dans une seule est unique page HTML, il s’agit donc d’être capable d’afficher les bons élements du DOM pour la bonne URL.
Avant de configurer le routeur de notre application, nous allons dans un premier temps créer des composants qui correspondront au différerntes routes de notre application. il est important de noter à cette étape que nous considérons le composant d’une route comme un composant principal dans lequel nous intégrerons d’autres composants.
Avant de créer nos composants principaux nous allons structurer notre application en créant dans le dossier app un dossier nommé routes dans lequel nous crérons les composants des routes :
```
mkdir src/app/routes
```
Une fois ce dossier créé nous pouvonos générer nos [composants](https://angular.io/guide/architecture-components) principaux avec la commande suivante :
```
ng g c routes/homePage -is
```
> Le drapeau `-is` permet de créer un composant sans y ajouter de CSS.
Cette commande à créée trois différents fichiers qui nous seront ensuite utiles pour définir le contenu de notre page d'accueil. Nous répettons à présent la commandes précédente pour avoir en tout les dossier suivants dans le dossier `routes` :
- connected-page pour un utilisateur connecté
- home-page pour afficher une page d'acceil
Le contenu des fichiers de nos différrents [composants](https://angular.io/guide/architecture-components) principaux seront éditer plus tard, nous allons avant cela configurer le module de [routing][https://angular.io/guide/router] que nous allons utiliser dans notre application. Ce fichier à pour but de distruber le bon [composant](https://angular.io/guide/architecture-components) principal selon les routes que nous allons définir.
Nous créons donc un fichier nommé `app.router.ts` à la racine de notre dossier `app` :
```
touch src/app/app.router.ts
```
Nous ouvrons ce fichier et y collons le code qui permet d'initier notre module de [routing][https://angular.io/guide/router] :
```typescript=
/*
Imports
*/
// Angular
import { Routes } from '@angular/router';
//
/*
Export
*/
export const AppRouterModule: Routes = [];
//
```
Dans un premier temps nous importons la class `Routes` dans le fichier ce qui nous permet ensuite d'exporter une constante nommée `AppRouterModule` que nous typons en utilisant la class `Routes` en définition.
Nous pouvons à présent importer le composant principal `HomePageComponent` après l'import de la class `Routes` :
```typescript=
// Inner
import { HomePageComponent } from "./routes/home-page/home-page.component";
```
Nous importons le [composant](https://angular.io/guide/architecture-components) principal dans notre module de [routing][https://angular.io/guide/router] car nous en avons besoin pour l'ajouter dans notre constante `AppRouterModule`. Avec [Angular](https://angular.io) pour définir une route il suffit d'ajouter dans la constante `AppRouterModule` un objet pour chaque route en définissant les propriétés suivantes :
```typescript=
{
path: '',
component: HomePageComponent
}
```
Nous allons donc à présent importer les autres [composants](https://angular.io/guide/architecture-components) principaux dans notre module de [routing][https://angular.io/guide/router] de telle sorte à configurer les routes suivantes :
- path `''` avec le compsant `HomePageComponent`
- path `'connected'`avec le composant `ConnectedPageComponent`
A la fin de cette étapes toutes nos routes sont configurées dans le module de [routing][https://angular.io/guide/router] de notre application, nous devons à présent l'intégrer dans le fichier `app.module.ts`. D'ordre général avec [Angular](https://angular.io) lorsque un module est créé il est obligatoire de le référencer dans le fichier `app.module.ts` pour quil soit disponible dans l'application.
Nous ouvons donc le fichier `app.module.ts` pour y importer la class `RouterModule` et notre module de [routing][https://angular.io/guide/router] :
```typescript=
// Router
import { RouterModule } from "@angular/router"
import { AppRouterModule } from "./app.router";
```
Nous pouvons à présent ajouter un item dans le tableau des imports du `@NgModule` :
```typescript=
...
imports: [
BrowserModule,
RouterModule.forRoot( AppRouterModule, { onSameUrlNavigation: 'reload' } ),
]
...
```
La configuration du module de [routing][https://angular.io/guide/router] de notre application est à présent terminé, il nous reste à éditer le fichier `app.component.ts` pour y intégrer la gestion de nos routes :
```typescript=
/*
Import
*/
// Angular
import { Component, OnInit } from '@angular/core';
//
/*
Componant configuration
*/
@Component({
selector: 'app-root',
template: `
<router-outlet></router-outlet>
`
})
//
/*
Componant class definition
*/
export class AppComponent implements OnInit {
constructor(){}
ngOnInit(){}
}
//
```
Nous pouvons a présent lancer la commande qui nous permet d'afficher l'application dans notre navigateur à l'adresse http://localhost:4200 :
```
ng serve
```
> Cette commande sert uniquement en phase de développement pour tester l'application.
---
# Gestion des composant de l'application
*Mise en place des composant de base d'une application Web*

## Principe de construction en "poupée russe"
Comme vu à l'étape précédente, un [composant](https://angular.io/guide/architecture-components) [Angular](https://angular.io) est constitué de plusieurs fichiers différents mais qu'il est important de définir les rôles qu'ils doivent jouer dans une application. Dans un premier temps nous avons vu les `composants principaux` que nous utilisons dans nos routes, nous allons à présent aborder les `composants enfants`.
Le rôle de des [composants](https://angular.io/guide/architecture-components) enfants est d'être intégres dans des [composants](https://angular.io/guide/architecture-components) principaux dans le but de les découper pour mieus les structurer.
Nous allons tout d'abord créer celui qui nous permettra de naviguer de route en route dans notre application, à savoir la navigations. Dans un premier temps nous créons un dossier à la racine du dossier `app` dans lequels nous crérons nos composants enfants :
```
mkdir src/app/shared
```
Une fois le dossier créer nos générons le [composant](https://angular.io/guide/architecture-components) enfant pour la navigation avec la commande suivnate :
```
ng g c shared/header -is
```
Il suffi à présent d'ajouter des balises HTML dans le fichier `header.component.html`, nous allons lui donner l'aspect d'un header HTML classique puis nous y intégrons des liens vers les endpoints que nous avons défini dans le fichier `app.router.ts` de la façon suivante :
```htmlmixed=
<a [routerLink]="'/'">Home</a>
```
Nous utilisons ici la directive [routerLink](https://angular.io/api/router/RouterLink) qui est disponible grâce à la configuration de notre [**rRouteur** https://angular.io/guide/router](https://angular.io/guide/router)[**routeur** https://angular.io/guide/router](https://angular.io/guide/router), nous ajoutons donc autant de lien que de endpoint défini dans le fichier `app.router.ts`.
Pour utiliser le [composant](https://angular.io/guide/architecture-components) `HeaderComponent` nous devons à présent utiliser le sélecteur auquel il correspond. Pour identifier ce sélecteur il suffi d'ouvrir le fichier `header.component.ts` pour repérer la valeur de la propriété `selector` du [décorateur](https://medium.com/@madhavmahesh/list-of-all-decorators-available-in-angular-71bdf4ad6976) `@Component` (en général "app-" plus le nom du composant). Il est possible à présent d'uiliser ce sélecteur dans notre application pour afficher afficher notre navigation
Nous ouvrons le fichier `app.component.ts` pour ajouter juste avant la balise `router-outlet` le sélecteur de notre [composant](https://angular.io/guide/architecture-components) `HeaderComponent` :
```typescript=
<app-header></app-header>
```
La gestion des routes de l'application est à présent terminée, nous pouvons tester notre configuration en nous rendant à l'adressee http://localhost:4200/ pour tester notre [composant](https://angular.io/guide/architecture-components) enfant et les routes qui doivent toutes afficher le [composant](https://angular.io/guide/architecture-components) principal associé.
---
---
# Gestion de l'information en Angular
*Gestion des requêtes asynchrones dans une application Web*

## Le principe de "Single page application"
Développer une application Web en Javascript c'est avant tout travailler sur une structure de code qui permet de nourrir un DOM avec des informations, suite à une interaction utilisateur. Ce principe nécessite à la fois de connaître l'état de l'interface graphique et celui de l'information afin de présenter dans le navigateur les éléments qui correspondent à une requête utilisateur.
Le principe théorique à mettre en place ne date pas d'hier, dans la mesure où l'informatique moderne, qui se base sur le pattern MVC, a déjà dû répondre à cette problématique. Le pattern MVC est donc la base sur laquelle nous devons baser toutes nos réflexions en terme de développement. C'est en revanche les contraintes liées au Web qui doivent diriger notre réflexion quant à l'adaptation du pattern MVC dans le développement d'une application Web.
Les différents cadritiels Front ont des techniques qui se rapprochent, tant la problématique est commune à tous les projets qui gèrent des données. C'est en la matière les équipes qui développent React qui ont mis défini un nouveau pattern qui est à également utilisable avec Angular en basant la gestion de l'information sur le principe de RXjs.
## Création d'un service "Injectable"
La gestion des [services](https://angular.io/guide/architecture-services) est l'un des aspects principaux à bien comprendre en [Angular](https://angular.io) dans la mesure où une application Web est alimentée par des données [asynchrones](https://fr.wikipedia.org/wiki/Ajax_(informatique)), il est primordiale de bien comprendre le principe de [Single page application](https://en.wikipedia.org/wiki/Single-page_application) et celui de [Promise](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise) pour aborder celle plus spécifique des [services](https://angular.io/guide/architecture-services) [Angular](https://angular.io).
Les [services](https://angular.io/guide/architecture-services) [Angular](https://angular.io) peuvent être séparés en deux catégories distinctes : les [Injectables](https://angular.io/api/core/Injectable) et les [Observables](https://rxjs-dev.firebaseapp.com/guide/observable). Dans notre démonstration nous les utilisons soit pour récupérer ou envoyer des informations via le protocole [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) soit pour distribuer cette information dans notre application. Nous commançons par mettre en place un service [Injectables](https://angular.io/api/core/Injectable) car c'est lui qui nous permettra d'exécuter des requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) dans notre application.
Pour commencer nous devons importer un module spécifique et le définir dans le fichier `app.module.ts` que nous ouvrons pour importer le module [HttpClientModule](https://angular.io/guide/http) :
```typescript=
import { HttpClientModule } from "@angular/common/http";
```
Comme pour tous les modules [Angular](https://angular.io) nous devons ajouter [HttpClientModule](https://angular.io/guide/http) dans le tableau des imports du décorateur `@NgModule` afin de rendre disponible les requêtes HTTP :
```typescript=
imports: [
...
HttpClientModule
]
```
Nous pouvons à présent créer notre [service](https://angular.io/guide/architecture-services) [Angular](https://angular.io) qui permet d'organiser les requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) dans notre application de manière à la structurer un maximum. Nous allons dans un premier temps créer un dossier `services` à la racine de notre dossier `app` :
```
mkdir src/app/services
```
Une fois ce dossier créé nous pouvons y ajouter notre premier [service](https://angular.io/guide/architecture-services) avec la commande suivantes :
```
ng g s services/crud/crud
```
Nous avons à présent un fichier `crud.service.ts` placé dans le dossier `services > crud`, nous pouvons l'ouvrir ce fichier pour commencer la configuration du service avec le code suivant :
```typescript=
// Angular
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
//
/*
Definition
*/
@Injectable()
export class CrudService {
// Inject module(s) in the service
constructor( private HttpClient: HttpClient ){};
/*
Methods to get API responses
*/
// Get the API response
private getData = (apiResponse: any) => apiResponse || {};
// Get the API error
private handleError = (apiError: any) => Promise.reject(apiError.error);
//
};
//
```
Dans un premier temps nous importons la class `HttpClient` dans le fichier pour pouvoir utiliser les requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) dans le [service](https://angular.io/guide/architecture-services) et nous injecton la class `HttpClient` en créant une propriété privée nommée également `HttpClient` dans le constructeur. Nous créons ensuite deux méthodes dans le service qui nous permettrons d'analyser le retour des requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol).
Nous pouvons à présent nous intéresser au principe du [CRUD](https://fr.wikipedia.org/wiki/CRUD) dans notre [service](https://angular.io/guide/architecture-services) en ajoutant des méthodes qui nous permettront d'exécuter les différents types de requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol). Les premières méthodes que nous allons créer sont celles qui permettent d'exécuter des requêtes de type `GET` vers une URL. Nous nous plaçon en dessous du constructeur et nous ajoutons le code suivant :
```typescript=
// CRUD method: read item
public readOneItem(param: String): Promise<any>{
return this.HttpClient.get(`https://jsonplaceholder.typicode.com/posts?${param}`)
.toPromise().then(this.getData).catch(this.handleError);
};
// CRUD method: read all items
public readAllItems(): Promise<any>{
return this.HttpClient.get(`https://jsonplaceholder.typicode.com/posts/`)
.toPromise().then(this.getData).catch(this.handleError);
};
```
Dans ces deux méthodes nous utilisons la fonction `get()` de la propriété `HttpClient` que nous avons créé dans le constructeur. La différrence notable entre ces deux méthodes est le fait d'intégrer ou non un paramètre `param` en fin d'URL. Nous pouvons à présent passer à la suite des méthodes du [CRUD](https://fr.wikipedia.org/wiki/CRUD) mais nous devons tout d'abord intégrer un nouveau module dans le [service](https://angular.io/guide/architecture-services) en modifiant un de nos imports de cette façon :
```typescript=
import { HttpClient, HttpHeaders } from '@angular/common/http';
```
Nous ajoutons la class `HttpHeaders` car pour les requêtes de type `POST` par exemple ne devons définir la méthode de communication que nous allons utiliser dans nos requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol). Dans la plupart des cas le format de donnée [JSON](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation) est utilisé dans les échanges d'informations en [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) mais il est possible d'envoyer un grand nombre de format de données différents.
Nous nous plaçon en-dessous des dernières méthodes du [CRUD](https://fr.wikipedia.org/wiki/CRUD) que nous avons créé pour ajouter une méthode qui permet d'exécuter des requêtes de type `POST` vers une URL :
```typescript=
// CRUD method: create item
public createItem(data: any): Promise<any>{
// Set header
let myHeader = new HttpHeaders();
myHeader.append('Content-Type', 'application/json');
// Launch request
return this.HttpClient.post(`https://jsonplaceholder.typicode.com/posts`, data, { headers: myHeader })
.toPromise().then(this.getData).catch(this.handleError);
};
```
Nous utilisons dans cette nouvelle méthode la méthode `post()` de la propriété `HttpClient`, cette dernière nécessite en paramêtre en plus de l'URL les données à envoyer ainsi que le header que nous avons configuré dans la variable `myHeader`.
Après la création de c'est trois méthodes il est à constaté que la propriété `HttpClient` contient différentes méthodes qui correspondent aux types de requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) que nous utilisons dans notre [CRUD](https://fr.wikipedia.org/wiki/CRUD). Nous en déduisons donc que les méthodes `update` et `delete` exitent également, ce qui nous permet de créer les deux dernières méthodes qui nous permettent d'exécuter des requêtes de type `PUT` et `DELETE` vers une URL :
```typescript=
// CRUD method: edit an item
public updateItem(_id: String, data: any): Promise<any>{
// Set header
let myHeader = new HttpHeaders();
myHeader.append('Content-Type', 'application/json');
// Launch request
return this.HttpClient.put(`https://jsonplaceholder.typicode.com/posts/${_id}`, data, { headers: myHeader })
.toPromise().then(this.getData).catch(this.handleError);
};
// CRUD method: delete an item
public deleteItem(_id: String): Promise<any>{
// Set header
let myHeader = new HttpHeaders();
myHeader.append('Content-Type', 'application/json');
// Launch request
return this.HttpClient.delete(`https://jsonplaceholder.typicode.com/posts/${_id}`, { headers: myHeader })
.toPromise().then(this.getData).catch(this.handleError);
};
```
Nous conservons la même logique d'utilisation de paramêtre dans nos méthodes pour identifier précisément la donné à atteindre et dans le cadre des requête de type `PUT` pour envoyer des donnés vers l'URL.
Toutes les méthodes de notre [service](https://angular.io/guide/architecture-services) étant mises en place, nous devons à présent éditer le fichier `app.module.ts` car, à la manière de notre module de [routing](https://angular.io/guide/router), nous devons importer notre [service](https://angular.io/guide/architecture-services) pour qu'il soit disponible dans notre application. Nous ouvrons donc le fichier `app.module.ts` pour importer le service de cette manière :
```typescript=
import { CrudService } from "./services/crud/crud.service";
```
Puis nous ajoutons notre [service](https://angular.io/guide/architecture-services) dans le [décorateur](https://medium.com/@madhavmahesh/list-of-all-decorators-available-in-angular-71bdf4ad6976) `@NgModule` au niveau du tableau des providers :
```typescript=
@NgModule({
...
providers: [CrudService],
...
})
```
## Création d'un service "Observable"
Nous allons à présent aborder l'utilisation des [Observables](https://rxjs-dev.firebaseapp.com/guide/observable) dans un service [Angular](https://angular.io) qui peuvent être comparrés aux notions de STORE dans la mesure ou les [Observables](https://rxjs-dev.firebaseapp.com/guide/observable) permettent de distribuer l'information dans une application.
Il faut considérer les [Observables](https://rxjs-dev.firebaseapp.com/guide/observable) comme des sujets auxquels un [composant](https://angular.io/guide/architecture-components) peut s'abonner (*subscribe*) ou publier (*publish*), chaque [composant](https://angular.io/guide/architecture-components) abonné à un sujet est mit à jour automatiquement lorsque qu'un autre [composant](https://angular.io/guide/architecture-components) publie une mise à jour du sujet. Nous allons donc à présent créer un nouveau [service](https://angular.io/guide/architecture-services) pour mettre en pratique cette logique :
```
ng g s services/observable/observable
```
Nous allons tout d'abord configurer ce nouveaeu [service](https://angular.io/guide/architecture-services) en y important les class `BehaviorSubject` et `Observable` dans le fichier `observable.service.ts` :
```typescript=
/*
Imports
*/
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
//
/*
Definition and export
*/
@Injectable({
providedIn: 'root'
})
export class ObservablesService {
constructor() {}
}
//
```
La structure de ce fichier est similaire au fichier `crud.service.ts` si ce n'est que nous importons deux class suplémentaires pour que nous puission gérer nos [Observables](https://rxjs-dev.firebaseapp.com/guide/observable). Nous allons commencer par définir un sujet car c'est par lui que nos [composant](https://angular.io/guide/architecture-components) pourront partager des informations, nous plaçons sous le constructeur puis nous ajoutons un sujet, c'est à dire une propriété nommée `userInfo` :
```typescript=
protected userInfo: BehaviorSubject<any> = new BehaviorSubject<any>(null);
```
La propriété `userInfo` est protégée, c'est à dire qu'il est impossible d'en connaître la valeur hors du [service](https://angular.io/guide/architecture-services) `ObservablesService`, c'est pourquoi il faut à présent ajouter une méthode qui permettra aux composants qui s'abonnent à cette information d'en récupérer la valeur :
```typescript=
public getUserInfo(): Observable<any> { return this.userInfo };
```
Nous allons à présent permettre à des [composants](https://angular.io/guide/architecture-components) de mettre à jour la valeur de `userInfo`, dans la mesure ou la propriété est protégée, nous devons ajouter la fonction suivante :
```typescript=
public setObservableData = (type: string, data: any) => {
switch(type){
case 'user':
this.userInfo.next(data);
break;
default:
break;
};
};
```
> La fonction `next()` permet de mettre à jour la valeur de `userInfo`.
Cette méthode prend deux paramêtre, `type` nous permettra d'utiliser cette méthode pour plusieurs [Observables](https://rxjs-dev.firebaseapp.com/guide/observable) et `data` qui permettra de mettre à les propriétés protégées de notre [service](https://angular.io/guide/architecture-services). Nous voulons que deux sujets soient défini dans notre applications pour permettre de les partager dans nos [composants](https://angular.io/guide/architecture-components), c'est pourquoi nous ajoutons le code nécessaire pour définir les deux sujets suivants :
- userInfo pour partager les informations d'un utilisateur connecté
- postList Pour partager une liste d'articles
Notre [service](https://angular.io/guide/architecture-services) est à présent configuré correctement mais nous devons, comme pour le service [Injectable](https://angular.io/api/core/Injectable) l'importer dans le fichier `app.module.ts` pour ajouter la class `ObservablesService` dans le tableau des providers afin qu'il soit disponible dans notre application.
## Connecter le service Injectable au service Observable
Notre application dispose à présents de deux [services](https://angular.io/guide/architecture-services) différent, un [Injectable](https://angular.io/api/core/Injectable) qui permet d'éxécuter des requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) et un [Observable](https://rxjs-dev.firebaseapp.com/guide/observable) qui permet de partageer des information dans notre application mais comment faire communiquer les deux ? Nous allons tout d'abord faire un sorte qu'une valeur puisse être mise à jour en partant du principe suivant : lorsqu'un utilisateur se connect toutes ses informations sont partagées dans l'application.
Nous ouvrons donc à présent le fichier `crud.service.ts`, nous allons ajouter un paramêtre `endpoint` aux métodes `readOneItem()` et `getData()` qui nous permettra d'ajouter un `switch` dans la méthode `getData()` pour mettre à jour la bonne information dans le service [Observable](https://rxjs-dev.firebaseapp.com/guide/observable).
Nous devons tout d'abord importer notre class `ObservablesService` pour l'injecter dans le constructeur de la class `CrudService` :
```typescript=
import { ObservablesService } from "../observable/observable.service";
@Injectable()
export class CrudService {
constructor(
private HttpClient: HttpClient,
private ObservablesService: ObservablesService
){};
...
}
```
Comme pour la class `HttpClient` nous crééons une prépriété privée nommé `ObservablesService` puis nous mettons à jour les fonctions `readOneItem()` et `getData()` :
```typescript=
public readOneItem(endpoint: String, param: String): Promise<any>{
return this.HttpClient.get(`https://jsonplaceholder.typicode.com/${endpoint}?${param}`).toPromise()
.then( data => this.getData(endpoint, data))
.catch(this.handleError);
};
private getData = (endpoint, apiResponse: any) => {
// Switch endpoint to set observable value
switch(endpoint){
case 'users':
// Set user info obserrbale value
this.ObservablesService.setObservableData('user',apiResponse)
// Return data
return apiResponse || {};
break;
default:
// Retun data anytime
return apiResponse || {};
break;
};
};
```
Les modifications que nous venons d'apporter sur le fichire `crud.service.ts` au niveau de la méthode `getData()` nécessite la mise à jour des autres méthodes du [CRUD](https://fr.wikipedia.org/wiki/CRUD) pour y intégrer la paramêtre `endpoint` et un `case` dans la méthode `getData()` pour pourvoir mettre à jour la valeur de la propriété `postList` pour finaliser la mise à jour du fichier `crud.service.ts`.
## Utiliser un service Injectable dans un composant
Il est possible d'utiliser un ou plusieurs [services](https://angular.io/guide/architecture-services) dans un [composant](https://angular.io/guide/architecture-components) principal comme dans un [composant](https://angular.io/guide/architecture-components) enfant, dans le cadre de notre projet nous allons préférer utiliser le [service](https://angular.io/guide/architecture-services) `CrudService` dans nos [composants](https://angular.io/guide/architecture-components) principaux car cela permet de bien structurer les échanges d'informations.
Les étapes à suivre reste les mêmes pour intégrer des [services](https://angular.io/guide/architecture-services), nous prenons en exemple le fichier `app.component.ts` dans lequel nous importons et le [service](https://angular.io/guide/architecture-services) `CrudService` :
```typescript=
import { CrudService } from "./services/crud/crud.service";
```
Puis nous ajoutons une propriété privée dans le constructeur :
```typescript=
constructor(
private CrudService: CrudService
){}
```
Le fichier `home-page.component.ts` constitue le point d'entré de notre application, c'est pourquoi nous allons y ajouter une méthode qui permet de tester une adressse email pour savoir si elle fait partie de la liste des utilisateurs. Nous nous plaçon souus le constructeur puis nous ajoutons le code suivant :
```typescript=
private getUserInfo = (email: String ) => {
// Use CrudService to get user infos
this.CrudService.readOneItem('users', `email=${email}`)
.then( data => {
console.log('SUCCES request', data);
})
.catch( error => {
console.log('ERROR request', error);
});
};
```
Puis, pour lancer cette méthode dès le chargement du [composant](https://angular.io/guide/architecture-components) `HomePageComponent` nous éditons la méthode `ngOnInit()` :
```typescript=
ngOnInit(){
this.getUserInfo('Sincere@april.biz');
};
```
> Nous mettons en paramêtre une adresse email valide par default afin de tester la méthode `getUserInfo()`.
Avec l'intégration du [service](https://angular.io/guide/architecture-services) `CrudService` et l'utilisation de sa méthode `readOneItem()` dans le fichier `app.component.ts` nous venons de comprendre comment utiliser les méthodes d'un [service](https://angular.io/guide/architecture-services) dans un [composant](https://angular.io/guide/architecture-components), ce qui nous sera utile quand nous mettron à jour les [composants](https://angular.io/guide/architecture-components) des différentes routes de notre application.
## Utiliser un service Observable dans un composant
La méthode `getUserInfo()` que nous avons ajouté dans le fichier `app.component.ts` utilise la méthode `readOneItem()` de notre [service](https://angular.io/guide/architecture-services) `CrudService`, dans la mesure ou nos deux [services](https://angular.io/guide/architecture-services) sont connecté l'un à l'autre cela veut dire que lorsque la méthode `getData()` est appelée avec en paramètre `users` comme `endpoint`, les données reçus sont publiées en tant que nouveau sujet pour l'[observable](https://rxjs-dev.firebaseapp.com/guide/observable) `userInfo`. Le but d'un [observable](https://rxjs-dev.firebaseapp.com/guide/observable) étant de partager des informations entre le [composant](https://angular.io/guide/architecture-components), nous pouvons à présent faire en sorte d'afficher une navigation différente pour un utilisateur connecté ou non.
Nous ouvrons donc le fichier `header.component.ts` pour y importer notre [service](https://angular.io/guide/architecture-services) `ObservablesService` en suivant les mêmes étapes que pour le [service](https://angular.io/guide/architecture-services) `CrudService`. Ensuite nous créons une propriété `userData` puis nous modifions le constructeur pour modifier la valeur de `userData` avec notre [service](https://angular.io/guide/architecture-services) `ObservablesService` :
```typescript=
export class HeaderComponent implements OnInit {
/*
Declaration
*/
// Properties
public userData: any;
constructor(
private ObservablesService: ObservablesService
){
// Get user data observer
this.ObservablesService.getUserInfo().subscribe( userDataObserver => {
if(userDataObserver === null) { this.userData = null }
else{ this.userData = userDataObserver[0] }
})
}
//
ngOnInit(){};
};
```
> La valeur de `userDataObserver` est un tableaeu, c'est pourquoi nous n'en récupérons que le premier index dans ce cas précis.
Il est possible à présent d'utiliser la propriété `userData` dans le fichier `header.component.html` pour ajouter une condition qui affiche le nom de l'utilisateur si la valeur de `userdata` est égale à `null` :
```htmlmixed=
<h1 *ngIf="userData !== null" [innerText]="userData.name"></h1>
```
Nous venons de voir comment mettre à jour une valeur grâce à l'utilissation du [service](https://angular.io/guide/architecture-services) `ObservablesService`, cette technique peut être appliquée pour tous types d'informations dans n'importe quel [composant](https://angular.io/guide/architecture-components) et s'avère très utile pour afficher des informations particulières sans avoir à répéter des requêtes [HTTP](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol) qui renvoie la même information.
---
## Ressources

> Index des liens vers les sujets traités dans ce document
- [**Angular** https://angular.io](https://angular.io)
- [**TypeScript** https://www.typescriptlang.org/](https://www.typescriptlang.org/)
- [**CLI** https://fr.wikipedia.org/wiki/Interface_en_ligne_de_commande](https://fr.wikipedia.org/wiki/Interface_en_ligne_de_commande)
- [**Angular CLI** https://cli.angular.io/](https://cli.angular.io/)
- [**Component** https://angular.io/guide/architecture-components](https://angular.io/guide/architecture-components)
- [**Routeur** https://angular.io/guide/router](https://angular.io/guide/router)
- [**HTTP** https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol)
- [**Endpoints** https://en.wikipedia.org/wiki/Web_API](https://en.wikipedia.org/wiki/Web_API)
- [**DOM** https://fr.wikipedia.org/wiki/Document_Object_Model](https://fr.wikipedia.org/wiki/Document_Object_Model)
- [**Directive routerLink** https://angular.io/api/router/RouterLink](https://angular.io/api/router/RouterLink)
- [**Angular décorator** https://medium.com/@madhavmahesh/list-of-all-decorators-available-in-angular-71bdf4ad6976](https://medium.com/@madhavmahesh/list-of-all-decorators-available-in-angular-71bdf4ad6976)
- [**Angular services** https://angular.io/guide/architecture-services](https://angular.io/guide/architecture-services)
- [**Web asynchrones** https://fr.wikipedia.org/wiki/Ajax_(informatique)](https://fr.wikipedia.org/wiki/Ajax_(informatique))
- [**Single page application** https://en.wikipedia.org/wiki/Single-page_application](https://en.wikipedia.org/wiki/Single-page_application)
- [**Promise** https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise)
- [**Injectables** https://angular.io/api/core/Injectable](https://angular.io/api/core/Injectable)
- [**Observables** https://rxjs-dev.firebaseapp.com/guide/observable](https://rxjs-dev.firebaseapp.com/guide/observable)
- [**HttpClientModule** https://angular.io/guide/http](https://angular.io/guide/http)
- [**CRUD** https://fr.wikipedia.org/wiki/CRUD](https://fr.wikipedia.org/wiki/CRUD)
- [**JSON** https://fr.wikipedia.org/wiki/JavaScript_Object_Notation](https://fr.wikipedia.org/wiki/JavaScript_Object_Notation)
- [**DOM dynamique** https://fr.wikipedia.org/wiki/HTML_dynamique](https://fr.wikipedia.org/wiki/HTML_dynamique)
- [**API** https://fr.wikipedia.org/wiki/Interface_de_programmation](https://fr.wikipedia.org/wiki/Interface_de_programmation)