Chaker BEN MAHMOUD 2023
Angular
Framework JavaScript, open source, présenté par Google en
2009
Permettant de créer des applications
– Front-End
– mono-page (SPA)
– utilisant les composants webs
Basé sur un concept connu en programmation orientée objet
Injection de dépendance : consistant à utiliser des classes
sans faire de l’instanciation statique
Page 2
Angular
Page 3
Angular
Page 4
Angular
Les différentes versions d’Angular
– Angular 1 (ou AngularJS) présenté en 2009 : utilisant le JavaScript
– Angular 2 présenté en octobre 2014 : remplacement du JS par TS
– Angular 4 présenté en décembre 2016
– Angular 5 présenté en novembre 2017
– Angular 6 présenté en mai 2018
– Angular 7 présenté en Octobre 2018
– ……………
– Angular 16 présenté en mai 2023
– Angular 17 présenté en novembre 2023
– Angular 18 présenté en septembre 2024
Page 5
Angular
Page 6
Angular
Pour la version 16/17/18 (création d’un projet)
ng new my-app --no-standalone
o ng new : Cette commande crée un nouveau projet Angular.
o my-app : C'est le nom du répertoire qui sera créé pour
votre projet. Vous pouvez le remplacer par le nom souhaité.
o --no-standalone : Cette option désactive l'utilisation des
composants autonomes, ce qui signifie que vous devrez
utiliser le module principal AppModule pour gérer votre
application.
Page 7
Angular
Arborescence d’un projet Angular
e2e : contenant les fichiers permettant de tester l’application
node_modules : contenant les fichiers nécessaires de la
librairie nodeJS
src : contenant les fichiers sources de l’application
[Link] : contenant l’ensemble de dépendance de
l’application
.[Link] : contenant les données concernant la
configuration du projet
[Link] : contenant les données sur les règles à respecter
par le développeur
Page 8
Angular
Page 9
Angular
Architecture
Page 10
Angular
Contenu d’ [Link]
@NgModule(
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
• @NgModule : pour déclarer cette classe comme module
• declarations : dans cette section, on déclare les composants de ce module
• imports : dans cette section, on déclare les modules nécessaires pour le module
• providers : ici, on déclare les services qui seront utilisés dans le module
• bootstrap : dans cette section, on déclare le composant principal de ce module
Page 11
Angular
Le fichier [Link] Le fichier [Link]
@Component({ <div style="text-align:center">
selector: 'app-root’, <h1>
templateUrl: './[Link]’, Welcome to {{ title }}!
styleUrls: ['./[Link]'] </h1>
}) ...
export class AppComponent { </div>
title = 'App2';
}
• @Component : pour déclarer cette classe comme composant web
• selector : pour définir le nom de balise correspondant à ce composant web
• templateUrl : pour indiquer le fichier contenant le code HTML correspondant
au composant web
• styleUrls : pour indiquer le(s) fichier(s) contenant le code CSS correspondant
au composant web
Welcome to {{ title }} : title sera remplacé par sa valeur dans [Link]
Page 12
Angular
Les directives
– *ngFor
– *ngIf
– *ngSwitch
– ng-container
– ng-template
Page 13
Angular
Soit le tableau suivant : tab:number[]=[2,3,5,8];
Afficher le tableau tab en utilisant *ngFor
<ul>
<li *ngFor = "let elt of tab">
{{ elt }}
</li>
</ul>
Et pour avoir l’indice de l’itération courante
<ul>
<li *ngFor = "let elt of tab; let i = index">
{{ i }} : {{ elt }}
</li>
</ul>
Page 14
Angular
Si on veut tester puis afficher si le premier élément est impair
<ul>
<li *ngIf = "tab[0]%2 != 0">
{{ tab[0] }} est impair
</li>
</ul>
Si on veut tester puis afficher la parité du premier élément
<ul>
<li *ngIf="tab[0]%2 != 0; else sinon">
{{ tab[0] }} est impair
</li>
<ng-template #sinon>
<li>
{{ tab[0] }} est pair
</li>
</ng-template>
</ul>
Page 15
Angular
Exercice : Ecrire un code HTML, en utilisant les directives Angular, qui permet
d’afficher sous forme d’une liste chaque élément du tableau précédent ainsi
que sa parité.
<ul>
<ng-container *ngFor="let elt of tab">
<li *ngIf="elt % 2 != 0; else sinon">
{{ elt }} est impair
</li>
<ng-template #sinon>
<li> {{ elt }} est pair </li>
</ng-template>
</ng-container>
</ul>
Remarque : ng-container et ng-template n’apparaîtront pas dans le
DOM de la page.
Page 16
Angular
Ecrire un code HTML, en utilisant les directives Angular, qui permet d’afficher sous
forme d’une liste chaque élément d’un tableau avec un message défini ainsi :
• Si la valeur est comprise entre 0 et 9 : échec
• Si elle est entre 10 et 13 : moyen
• Si elle est entre 14 et 16 : bien
• Sinon : très bien
<ul>
<ng-container *ngFor="let elt of tab">
<ng-container [ngSwitch]="true">
<li *ngSwitchCase="elt < 10"> {{elt}} : echec </li>
<li *ngSwitchCase="elt >= 10 && elt < 13"> {{elt}}: moyen </li>
<li *ngSwitchCase="elt >= 13 && elt < 15"> {{elt}}: bien </li>
<li *ngSwitchCase="elt >= 15"> {{elt}} : tres bien </li>
<li *ngSwitchDefault> autre </li>
</ng-container>
</ng-container>
</ul>
Page 17
Routage
Page 18
Routage
Dans un framework front-end (comme Angular), il n'est pas souhaitable
de perdre tout son contexte à chaque changement de page.
Angular a donc besoin d'un système de routage pour permettre
la navigation à travers différentes pages de votre application.
Pour réaliser ce routage, Angular propose le module RouterModule
disponible dans la librairie @angular/router.
Angular-CLI nous propose le module applicatif AppRoutingModule
permettant d'ajouter la fonctionnalité de routage à notre application :
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [];
@NgModule({
imports: [[Link](routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Page 19
Routage
Ce module importe deux éléments notables de la librairie @angular/router :
– Routes qui est un Array contenant la déclaration des Route
– RouterModule est un module regroupant les directives et les services
paramétrables permettant de remplir la fonctionnalité de routage.
On retrouve aussi la méthode statique forRoot() qui prend en paramètre un
tableau de Route,
Nous sommes donc face à un module permettant d'apporter les services et
directives à notre application via l'import de ce dernier au niveau du module
root AppModule.
@NgModule({
………………………………………
imports: [
BrowserModule,
AppRoutingModule
],
………………………………………
})
export class AppModule { }
Page 20
Routage
Si l'on reprend les bases d'une application SPA, lorsque l'utilisateur
clique sur un lien, une fonction Javascript est lancée avec
le path en paramètre.
Cette fonction va se charger de récupérer la page liée à ce path à
l'aide d'une table de routage et va afficher le contenu de cette
dernière dans une <div> spécifiée dans la page html,
Contrairement à une application Web classique, il n'est pas possible
d'utiliser l'attribut href dans vos balises lien <a>.
Comme nous l'avons vu, cela entraîne un rechargement de la page et une
perte de notre contexte Javascript.
Angular nous fournit donc une directive en remplacement : routerLink.
Cette directive attendant un tableau contenant un path et des paramètres
optionnels,
Page 21
Routage
Une fois nos liens déclarés, il est nécessaire d'indiquer à Angular où sera
chargé le contenu du lien (la fameuse <div>).
Cela se fait simplement à l'aide de la directive <router-outlet> qui va
accueillir le contenu de la route.
Cela nous donne ainsi le Template suivant :
<hr>
<nav>
<a [routerLink]="['/']">Accueil</a>
<a [routerLink]="['/page1']">Page 1</a>
</nav>
<hr>
<router-outlet></router-outlet>
Page 22
Routage
Ou bien : =>
<hr>
<nav>
<a routerLink="/">Accueil</a>
<a routerLink="/page1">Page 1</a>
</nav>
<hr>
<router-outlet></router-outlet>
Page 23
Routage
On va maintenant définir la table de routage au niveau du module
AppRoutingModule que nous a généré Angular-CLI.
Pour cela, nous allons lister dans le tableau de type Routes de notre
module, les Route de notre application.
Une Route est l'association d'un path (partie d'une URL) et
d'un Component et c'est ce Component qui sera intégré dans la
balise <router-outlet>.
const routes: Routes = [
{ path: '', component: AccueilComponent },
{ path: 'page1', component: Page1Component },
];
Si path : '' => par défaut, le component Acceuil
sera affiché dans le router-outlet
Page 24
Routage
Comment faire ?
Etape 1 : On va créer deux Components et un service
ng g c Liste ng g c Ajout ng g s Gestion
Etape 2 : Dans [Link] , on va ajouter les modules nécessaires
@NgModule({
declarations: [
AppComponent,ListeComponent,AjoutComponent
],
imports: [
BrowserModule, HttpClientModule, FormsModule,AppRoutingModule
],
providers: [GestionService],
bootstrap: [AppComponent]
})
export class AppModule { }
Page 25
Routage
Etape 3 : Dans [Link] , on va ajouter les routes dans la
variable routes
const routes: Routes = [
{path:'', component : ListeComponent },
{path:'liste', component : ListeComponent },
{path:'ajout', component : AjoutComponent }
];
Etape 4 : Dans [Link] , on va définir les routerlink et la
router-outlet
<nav>
<a [routerLink]="['/liste']"> Liste des Départements</a>
<a [routerLink]="['/ajout']"> Ajouter un Département</a>
</nav>
<hr>
<router-outlet></router-outlet>
Page 26
Routage
Remarques 1
Une route peut porter un paramètre => /departement/5 (Que Faire ?)
1. Dans la table de routage, on définit le routage
{ path: 'departement/:id', component : DetailComponent }
2. Le lien dans la page html doit être sous cette forme
<a [routerLink]=“['/departement/{{[Link]}}']" > Détail </a>
3. L’accès aux paramètres, se fait via le service ActivatedRoute
numero : number;
constructor(private ac: ActivatedRoute) {
[Link] = [Link]["id"];
}
Page 27
Routage
Remarques 2
Pour faire une redirection dans votre code :
1. Injecter le module Router
constructor( private route:Router ) { }
=> bien sûr vous devez importer le module Router
import { Router } from '@angular/router';
2. Dans l’emplacement souhaité (dans un .[Link] )
[Link](["/liste"])
s’il est possède des paramètres
[Link](["/liste", id])
Page 28
Les Guards
Un Guard sur Angular est une fonctionnalité qui vous permet de contrôler l'accès
à des routes spécifiques dans votre application.
Vous pouvez utiliser des guards pour exécuter certaines vérifications ou actions
avant de permettre l'accès à une route, par exemple pour vérifier si l'utilisateur est
authentifié ou a les droits d'accès appropriés.
Page 29
Les formulaires
Page 30
Forms
Un formulaire :
– un outil graphique que nous créons avec le langage de description HTML
– il permet à l’utilisateur de saisir des données et de les envoyer vers une
autre page, vers une base de données...
Angular nous facilite
– la récupération des données saisies
– la validation et le contrôle des valeurs saisies
– la gestion d’erreurs,…
Un évènement
– Une action appliquée par l’utilisateur ou simulée par le développeur sur
un .[Link]
un évènement déclenché => une méthode dans le
.[Link] associé exécutée
Page 31
Forms
Un évènement
– Une action appliquée par l’utilisateur ou simulée par le développeur sur
un .[Link]
un évènement déclenché => une méthode dans le
.[Link] associé exécutée
Dans la vue (.[Link])
<div>
<button (click)="direBonjour()"> cliquer </button>
</div>
Dans la Controller ( .[Link] )
direBonjour(){
[Link]("Bonjour")
}
Page 32
Forms
Plusieurs formes de binding
– {{ interpolation }} : permet de récupérer la valeur
d’un attribut déclarée dans le .[Link]
– [ one way binding ] : permet aussi de récupérer la
valeur d’un attribut déclarée dans le .[Link]
– ( event binding ) : permet au .[Link] de
récupérer des valeurs passées par le .[Link]
{{interpolation}} est un raccourci de [ one way binding ]
Page 33
Forms
Il est possible de combiner one way binding et event binding
Résultat : two way binding
Un changement de valeur dans .[Link] sera aperçu
dans .[Link] et un changement dans
.[Link] sera reçu dans .[Link]
Pour cette liaison bidirectionnelle, il nous faut la propriété ngModel
Pour pouvoir utiliser la propriété ngModel, il faut ajouter le module
FormsModule dans [Link]
import { FormsModule } from '@angular/forms';
imports: [
………
FormsModule
],
Page 34
Forms
@Component({
templateUrl: './[Link]'
})
export class BookFormComponent {
bookTitle: string;
}
liaison bidirectionnelle
<form>
<input name="title“ [(ngModel)]="bookTitle" >
</form>
Page 35
Forms
export class AjoutComponent {
dept: object = { "id": null, "description": "" }
constructor() { }
Ajouter() {
……………
}
}
<h4>Ajouter un Département</h4>
<input type="text" [(ngModel)] = "[Link]" />
<input type="submit" (click)="Ajouter()" >
Page 36
Les services
Page 37
Services
Page 38
Services
Page 39
Services
Pour créer un service : => ng generate service nomService
Ou aussi => ng g s nomService
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class GestionService {
constructor() { }
}
Remarque : On doit ajouter ce service dans la liste des providres du
contrôleur principal de l’application Angular ([Link])
providers: [nomService],
Page 40
Services
Dans une application Angular, la plupart des données proviennent d'API
ReST où les échanges de données se font via des requêtes HTTP.
Pour produire des requêtes HTTP, Angular fournit un service HttpClient qui
est un wrapper de la classe native (et vieillissante) XMLHttpRequest.
Le service HttpClient a pour avantages de :
– simplifier l'implémentation d'échanges HTTP,
– fournir les outils nécessaires pour faciliter l'implémentation des "tests
unitaires",
– se baser sur les Observables permettant ainsi :
• d'annuler les requêtes si nécessaire,
• de suivre la progression d'"upload" et de "download",
• d'implémenter des wrappers permettant de produire une "response" à partir
d'un résultat temporaire en cache puis le résultat reçu depuis l'API
Page 41
Services
Utilisation de HttpClient dans un service :
Etape 1 : Dans [Link] , on va ajouter le module HttpClientModule
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
HttpClientModule,
]
})
export class AppModule { }
Etape 2 : Dans le service déjà crée, on injecte le service HttpClient
import { HttpClient } from '@angular/common/http';
@Injectable({providedIn: 'root'})
export class GestionService {
constructor(private http:HttpClient) { }
}
Page 42
Services
A partir de la version Angular 17 et les versions suivantes, y
compris Angular 18, une nouvelle API a été introduite pour
simplifier la configuration des services comme HttpClient.
Plutôt que d'importer et de déclarer des modules comme
HttpClientModule dans le tableau imports AppModule , Angular
permet d'utiliser des fonctions de "fourniture" comme
provideHttpClient pour configurer des services au niveau des
providers.
Qu'est-ce que provideHttpClient ?
provideHttpClient est une fonction utilitaire introduite pour
simplifier la manière dont le client HTTP est configuré.
Cela permet une approche plus modulaire et plus simple, en
particulier avec la montée en puissance des "Standalone
Components" dans Angular.
Page 43
Services
import { AppRoutingModule } from './[Link]';
import { AppComponent } from './[Link]';
import { provideHttpClient } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent, ],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [
provideHttpClient(),
provideClientHydration()
],
bootstrap: [AppComponent]
})
export class AppModule { }
Page 44
Services
Nous pouvons maintenant récupérer les données par une API.
Pour communiquer avec une API, on doit utilisé les méthodes
standards: get, post, delete, put, …
getAllDepartement (){
return [Link]('[Link]
}
ajouterDepartement(dept:any) {
return [Link]("[Link] );
}
getDepartementById(id:number){
return [Link]("[Link]
}
Page 45
Services
En effet, ces méthodes retournent toujours un Observable.
Cet Observable est "lazy" et il faut donc subscribe pour déclencher le
traitement souhaité.
Pour utiliser ce service dans un composant, on doit l’injecter
@Component({ })
export class ListeComponent implements OnInit {
depts :any = [];
constructor(private gest:GestionService) { }
ngOnInit() {
[Link]. getAllDepartement().subscribe (
(data) => { [Link] = data; },
(erre) => { [Link](erre) ; }
)
}
}
Page 46
Services
Version de Subscribe à partir de Angular13
@Component({ })
export class ListeComponent implements OnInit {
depts :any = [];
constructor(private gest:GestionService) { }
ngOnInit() {
[Link]. getAllDepartement().subscribe (
{
next: (data: any) => { [Link] = data; },
error: (err: any) => { [Link](err) },
complete: () => { [Link]("finish!!!!") }
}
)
}
}
Page 47
Communication
entre les
composants
Page 48
Communication entre les composants
Le principe de la communication entre les composants :
Transmettre les données depuis le père vers le fils grâce à @input()
Transmettre les données depuis le fils vers le père grâce à @output()
Page 49
@input
Le décorateur @Input() dans un composant signifie que la
propriété peut recevoir sa valeur de son composant parent.
Page 50
@input
Configuration du composant parent
<h1> Liste des Magasins </h1>
<app-child [titre]="mesage"></app-child>
HTML
Configuration du composant enfant
import { Component,Input} from '@angular/core';
@Component({ selector: 'app-child’, …… })
export class ChildComponent {
TS
@Input() titre:any;
}
HTML
{{titre}}
Page 51
@output
Le décorateur @Output() dans un composant enfant permet
aux données de circuler de l'enfant vers le parent.
Page 52
@output
Configuration du composant enfant
import { Component, EventEmitter, Output } from '@angular/core';
@Component({ selector: 'app-child', …… })
export class ChildComponent {
@Output() dataEnvoyee= new EventEmitter<string>();
sendToParentMessage(){ [Link]("bonjour"); } TS
}
<button (click)="sendToParentMessage()">SendMessage</button>
HTML
Configuration du composant parent
export class ParentComponent {
msg:string="";
getDataFromChild(x: string) { [Link] = x; }
} TS
HTML
<app-child (dataEnvoyee)="getDataFromChild($event)"></app-child>
Message
Page 53 From Child: {{msg}}
Bootstrap
npm install --save bootstrap
npm install --save @fortawesome/fontawesome-free
Puis, dans [Link]
"styles": [
"src/[Link]",
"node_modules/@fortawesome/fontawesome-free/css/[Link]",
"node_modules/bootstrap/dist/css/[Link]"
],
Page 54