XMS1IE320 - Projet transversal

CM2 - Introduction à Angular

Master 1 ALMA - Année 2026/2027

30 septembre 2026

Dans l'épisode précédent...

  • Introduction du module
  • CM de rappel sur HTML/CSS

Aujourd'hui

  • Premier CM "plus technique"
  • Introduction à Angular et ses concepts

Contexte

Actuellement, les applications qu'on vous présente sont petites

Elles restent rapides à charger

Mais que se passerait-il si jamais on avait une application plus grosse ?

Exemple : un site de e-commerce

  • plusieurs écrans
  • plusieurs centaines de composants visuels
  • authentification
  • système de compte
  • panier
  • notifications
  • appels API
  • gestion d'état
  • interactions entre composants
  • et d'autres...

Applications lourdes

Aujourd'hui, les sites sont de plus en plus lourds

Recharger une page entière = coûteux

Besoin que les sites soient le plus fluide possible à naviguer, et essayer d'économiser des appels serveurs

→ C'est là qu'interviennent les SPA !

Les SPA

Single-Page Application

Page à chargement unique (au lancement du site Web)

Opposé aux MPA (Multi-Page Application)

Page classique VS SPA

Comparaison MPA-SPA

SPA = plus lourd au démarrage, mais navigation fluide

Système de navigation

Les SPA détournent le fonctionnement historique du navigateur

MPA : chargement du HTML à chaque action

SPA : application JS/TS qui intercepte la navigation pour modifier dynamiquement le contenu de la page

HTML/CSS ou Framework ?

Pour une plus grosse application, un framework est préférable

Permet de découper le site en plus petits éléments, d'assurer la navigation... mais aussi de gérer le flux de données reçu par l'application.

Mais surtout... HTML/CSS est statique

2 langages principaux pour les frameworks

JavaScript

Présenté rapidement la dernière fois

TypeScript

Basé sur JavaScript, mais avec des types statiques

Logo TypeScript

TypeScript

Langage de programmation développé par Microsoft

Objectif : améliorer et sécuriser la production de code JavaScript

"Sur-ensemble syntaxique" de JavaScript : tout code JS est compatible avec TS

Avantages de TypeScript ?

TypeScript est un langage fortement typé

Code plus lisible

Facilement maintenable

"Protège" mieux contre les erreurs

Offre des options supplémentaires, comme les interfaces

En savoir plus sur TypeScript

Dans l'onglet "Ressources" des TP

Logo TypeScript

Notez toutefois que ce contenu ne sera pas abordé dans les séances de TP

Plusieurs frameworks sur le marché

  • React (JavaScript)
  • Vue (JavaScript)
  • Angular (TypeScript)
  • Et d'autres...
Logo Angular

Angular

Framework pour le développement d'applications web

Développé et maintenu par Google, basé sur TypeScript

Spécialisé dans les SPA !

Historique d'Angular

2010 : sortie d'AngularJS

2016 : sortie d'Angular 2, sa réécriture en TypeScript

2 nouvelles versions par an depuis la sortie

Juin 2026 : Angular 22 (version actuelle)

Prévu en juin 2027 : Angular 23

Ce qu'offre Angular

Système de composant (encapsulation du code)

Signals (gestion dynamique des données)

Injection de dépendances

Système de routing

Système de formulaire

Installer Angular

Pour utiliser Angular, il faut installer son CLI

DÉFINITION

Un CLI (Command Line Interface) est un outil en ligne de commande qui permet d'interagir avec un logiciel ou un framework, en exécutant des commandes spécifiques pour effectuer des tâches telles que la création de projets, la génération de composants, la gestion des dépendances, etc.


							npm install -g @angular/cli
						

Créer un nouveau projet

Après avoir installé le CLI, vous pouvez créer un nouveau projet Angular :


							ng new nom-projet
						

Application générée par Angular

Structure d'une application Angular

Si on affiche que l'essentiel...

Structure d'une appli Angular, où l'ensemble des fichiers de configuration ont été retirés

index.html

Fichier index.html d'un projet Angular

main.ts

Fichier main.ts d'un projet Angular

Composant par défaut

Fichier app.ts d'un projet Angular

Les composants

DÉFINITION

Un composant est une brique d'interface qui regroupe une partie de la présentation et la logique nécessaire à son fonctionnement

Un composant est constitué de 3 éléments :

  • TypeScript (pour les données et les méthodes)
  • HTML (pour le template à afficher)
  • CSS (pour le style du composant)

Créer un composant

Pour générer un nouveau composant, tapez la commande suivante dans un terminal :

Version courte


								ng g c nom-composant
							

Version longue


								ng generate component nom-composant
							

Décorateur @Component


							@Component({
								selector: 'app-example',
								imports: [],
								templateUrl: './example.html', // Possible de mettre un template brut
								styleUrl: './example.css', // Possible de mettre un style brut
							})
						

Sélecteur de balise

Le sélecteur est le nom de la balise HTML utilisée pour insérer le composant dans le template.

Prenez l'exemple suivant :


								@Component({
									selector: 'app-product'
								})
							

Cette balise peut être utilisée dans le template pour insérer le composant :


								
							

Importer un composant


							import { Component } from '@angular/core';
							import { Card } from 'chemin/vers/mon/composant/card'; // Import ici

							@Component({
								selector: 'app-tp1',
								imports: [Card], // Attention à bien l'importer ici aussi !
								templateUrl: './tp1.html',
								styleUrl: './tp1.css',
							})
							export class Tp1 {
								// Mon code TypeScript
							}
						

Structure d'une application Angular

Une application Angular est un arbre de composants

Arbre de composants

Exemple : application de gestion d'inventaire

Application de gestion d'inventaire

Composants

Arbre de composants pour une app de gestion d'inventaire Arbre de composants pour une app de gestion d'inventaire Arbre de composants pour une app de gestion d'inventaire

Sous-composant

Arbre de composants pour une app de gestion d'inventaire

Arbre de composant

Arbre de composants pour une app de gestion d'inventaire

Notez ici que d'autres éléments peuvent s'ajouter à notre app

Templates et directives Angular

Prenons ce composant TypeScript en exemple :


							export class Product {
								name = 'Clavier';
								price = 79.99;

								buy() {
									console.log('Produit acheté');
								}
							}
						

String interpolation

Permet d'afficher la valeur d'une variable dynamiquement

Mettre le nom de la variable entre {{ }}


							

{{ name }}

{{ price }} €

Property binding

Permet de définir des valeurs pour des propriétés d'éléments HTML, de composants Angular, ...

Cela permet notamment de :

  • Activer/désactiver des boutons (via une condition)
  • Définir des classes/styles CSS en fonction de valeurs
  • Transmettre de données à un autre composant
  • ...

On met la property entre []

Exemple de property binding


							
							
							

String interpolation vs property binding

String interpolation : afficher une valeur dans le HTML

Property binding : modifier la propriété d'un élément ou d'un composant

Event binding

Permet d'ajouter des événements à des composants Angular

On met l'event entre ()


							
						

Et si... on combinait les 2 ?

Two-way binding

Permet d'à la fois de lier une valeur dans un élément tout en donnant la possibilité de propager des changements


							
						

Ici, affiche les données du champ, en plus d'affecter un événement au changement

Conditionnelles en Angular

Le template que vous affichez peut dépendre de l'état du composant


							@if (isLogged) {
								

Bienvenue !

} @else {

Veuillez vous connecter.

}

Parcours de liste d'objets

Vous pouvez parfois avoir plusieurs objets identiques à afficher sur votre page


							@for (product of products; track product.id) {
								
							}
						

Instruction de branchement

Inspiré du switch en JavaScript


							@switch (condition) {
								@case (caseA) {
									

Je réalise le cas A !

} @case (caseB) @case (caseC) {

Je réalise le cas B... ou peut-être le C ?

} @default {

Je suis le cas exécuté par défaut !

} }

D'autres directives moins utiles

@defer : utilisé pour faire un chargement différé d'un composant (lazy load)

@boundary & @error : équivalent de l'instruction try catch

@let : créer une variable locale

Projection de contenu

Si vous avez besoin d'afficher du contenu personnalisé pour un élément "générique"

Dans votre composant :


								[...]
								
								[...]
							

Dans votre code :


								
									
								
							

Exemple : la page TP

Arbre de composants pour une app de gestion d'inventaire

Formulaires dans Angular

Angular propose plusieurs façons de créer et gérer des formulaires :

  • Formulaires réactifs (Reactive Forms)
  • Formulaires basés sur les modèles (Template-driven Forms)

Formulaires réactifs

Les formulaires réactifs sont des formulaires plus robustes, réutilisables et faciles à tester.

Ils sont généralement utilisés pour des formulaires complexes ou lorsque vous avez besoin d'une logique de validation avancée.

Exemple : un formulaire complexe avec plusieurs champs et validations.

Formulaires basés sur les modèles

Les formulaires basés sur les modèles sont plus simples à mettre en place et conviennent bien aux formulaires simples.

Exemple : une barre de recherche, un champ de saisie, etc...

C'est ce qu'on va utiliser en TP !

Exemple de code

Changement dynamique de nom de variable

Côté TypeScript


								import { Component, signal } from '@angular/core';
								import { FormsModule } from '@angular/forms';

								@Component({
									imports: [FormsModule],
									selector: 'app-product',
									styleUrl: './product.css',
									templateUrl: './product.html',
								})
								export class Product {
									productName = signal('');
								}
							

Côté HTML


							

							

{{ productName() }}

Signal

Montré juste avant dans le code

Enveloppe une valeur, et envoie une notification aux consommateurs intéressés lorsque cette valeur change.

Mon application est jolie !

Mais comment je gère les données dans mon application ?

Deux possibilités

Possibilité n°1 : tout mettre dans le fichier TypeScript

Avantages

Plus simple à implémenter (?)

Inconvénients

Pas de séparation de responsabilité

Tout le code est concentré au même endroit

Pas réutilisable

Possibilité n°2

Les services

DÉFINITION

Un service est un bout de code réutilisable dans l'ensemble d'une application Angular qui permet de gérer la logique métier, la récupération des données et d'autres fonctions

Créer un service

Pour générer un nouveau service, tapez la commande suivante dans un terminal :

Version courte


								ng g s nom-service
							

Version longue


								ng generate service nom-service
							

Service généré par la commande


							import { Service } from '@angular/core';

							@Service()
							export class Auth {}
						

Super, je peux utiliser des données !

Comment faire pour les structurer ?

Les interfaces

DÉFINITION

Les interfaces en TypeScript permettent de définir des contrats au sein de votre code ainsi que de définir des formes personnalisées pour des types de données complexes.

Basiquement identique à la POO

Créer une interface

Pour générer une nouvelle interface, tapez la commande suivante dans un terminal :

Version courte


								ng g i nom-interface
							

Version longue


								ng generate interface nom-interface
							

Définition d'une interface


							interface Personne {
								nom: string;
								age: number;
								sePresenter(): void;
							}
						

Implémentation


							class Employe implements Personne {
								nom: string;
								age: number;

								constructor(nom: string, age: number) {
									this.nom = nom;
									this.age = age;
								}

								sePresenter() {
									console.log(`Je m'appelle ${this.nom} et j'ai ${this.age} ans.`);
								}
							}
						

Et dans le cadre d'Angular ?


							@Service()
							export class ProductsService {
								// Donnée factice (stub)
								Employe product = new Employe {
									nom = "Quentin",
									age = 22
								}

								// Appel HTTP (voir CM4)
								private http = inject(HttpClient);

								getEmploye(id: string): Observable {
									return this.http.get(`/api/employe/${nom}`);
								}
							}
						

J'ai des données maintenant !

Mais je veux que mon site ait plusieurs pages...

Les routes

DÉFINITION

Une route est un chemin d'accès à une page ou à une vue spécifique dans une application Angular

Créer une route

Pour créer une nouvelle route, il faut modifier le fichier app.routes.ts :


							export const routes: Routes = [
								{ 
									path: 'accueil', 
									component: Accueil
								},
								{ 
									path: 'produits', 
									component: Produits
								}
							];
						

Route de redirection

Un moyen de rediriger les utilisateurs vers une autre page


							export const routes: Routes = [
								{ 
									path: 'accueil', 
									component: Accueil
								},
								{ 
									path: 'produits', 
									component: Produits
								},
								{ 
									path: '**', 
									redirectTo: 'accueil' 
								}
							];
						

Il est également possible de faire des redirections conditionnelles.

Les paramètres de route

Vous pouvez passer des paramètres dans votre route pour personnaliser le contenu affiché


							// [...]
								{
									path: 'produits',
									component: Produits
								}
								{ 
									path: 'produit/:id', 
									component: Produit 
								},
								{ 
									path: '**', 
									redirectTo: 'accueil' 
								}
							];
						

http://localhost:4200/produit/1 est une URL valide

Un composant un peu spécial : RouterOutlet

C'est le composant qui vous permet de gérer l'ensemble de votre routing.

Il sert de "placeholder", et Angular le remplie dynamiquement en fonction de la valeur de la route

Avez-vous déjà essayé d'accéder aux TP avant leur publication ?

C'est impossible ?

C'est normal !

Les guards

DÉFINITION

Un guard est une fonctionnalité d'Angular qui permet de contrôler l'accès à des routes spécifiques dans votre application

Créer un guard

Pour générer un nouveau guard, tapez la commande suivante dans un terminal :

Version courte


								ng g g nom-guard
							

Version longue


								ng generate guard nom-guard
							

Différents types de guard

CanActivate

Détermine si un utilisateur peut utiliser la route

Utilisé généralement par défaut quand vous voulez faire fonctionner un guard

CanActivateChild

Détermine si un utilisateur peut accéder aux routes enfant d'une route parent

Utile quand vous voulez protéger une section entière de routes

CanDeactivate

Détermine si un utilisateur peut quitter une route

Utile si vous voulez éviter que quelqu'un quitte votre page si votre formulaire n'est pas sauvegardé

CanMatch

Réalise un contrôle, et détermine si un utilisateur peut accéder à une route

Utile si vous voulez faire du routing conditionnel, du A/B testing, ...

Par exemple, vous voulez faire en sorte qu'un admin ait accès à un panel, mais les utilisateurs par défaut soient redirigés vers une autre page.

Exemple d'un guard

Exemple du site de TP


							import { inject } from "@angular/core";
							import { CanActivateFn, Router } from '@angular/router';

							export const accesTpGuard: CanActivateFn = () => {
								const router = inject(Router); // Injection de dépendances

								router.navigate(['/']);
								return false;
							};
						

Exemple simple : interdiction d'accès à une page

Exemple plus complet


							import { inject } from '@angular/core';
							import { CanActivateFn, Router } from '@angular/router';
							import { AuthService } from '../services/auth.service';

							export const authGuard: CanActivateFn = (route, state) => {
								// Injections de dépendances
								const authService = inject(AuthService);
								const router = inject(Router);

								if (authService.getAuthenticated()) {
									return true;
								} else {
									router.navigate(['/login']);
									return false;
								}
							};
						

Guard d'accès après authentification

Ajouter un guard à une route


							export const routes: Routes = [
								{ 
									path: 'accueil', 
									component: Accueil
								},
								{ 
									path: 'produits', 
									component: Produits,
									canActivate: [AuthGuard]
								},
								[...]
							];
						

Mon application est quasiment complète !

Mais comment faire en sorte de partager de la donnée entre mes composants ?

Communication parent-enfant

Le plus simple des deux

Parent : utilise le property binding


							
						

Enfant : utilise l'intruction @Input


							import { Input } from '@angular/core';

							export class UserCardComponent {
								@Input() user: any;
							}
						

Communication enfant-parent

Enfant : utilise l'intruction @Output


						import { Output, EventEmitter } from '@angular/core';

						export class UserCardComponent {
							@Output()
							deleteUser = new EventEmitter();
							
							onDelete() {
								this.deleteUser.emit();
							}
						}
						

							
						

Parent : événement au moment de la réception


							
						

							removeUser() {
								console.log('Utilisateur supprimé');
							}
						

La prochaine fois

  • Angular plus avancé
  • Communication entre une API et une application Angular
  • Test d'interface

Sources