Samuel KAMDOUM FOLONG
Author
Communication entre composants dans Angular : Input, Output et Evenements Parent-Enfant
Dans une application Angular, les composants interagissent souvent en echangeant des donnees pour garantir le bon fonctionnement et la coherence de l'application.
Dans une application Angular, les composants interagissent souvent en echangeant des donnees pour garantir le bon fonctionnement et la coherence de l'application. Cet echange d'informations peut s'effectuer de plusieurs manieres, en fonction de la relation qui lie les composants, qu'il s'agisse d'une hierarchie parent-enfant ou d'une communication entre composants independants.
Angular offre quatre principales methodes pour echanger des donnees entre les composants :
- Communication entre conposants lies par une relation Parent - Enfant : Dans ce cas, l'echange de donnees s'effectue grace a des decorateurs comme
@Input()et@Output(). Ces outils permettent au composant parent de transmettre des donnees au composant enfant, et inversement via des evenements. - Communication via des Services : L'utilisation de services partages permet d'echanger des donnees entre des composants independants, qu'ils aient ou non une relation hierarchique. Les services Angular peuvent stocker des donnees ou transmettre des messages grace a des objets comme Subject ou BehaviorSubject.
- Communication via des variables ou methodes locales (
@ViewChild) : Cette methode permet au composant parent d'acceder directement aux proprietes et aux methodes d'un composant enfant grace au decorateur@ViewChild. Cela est utile pour des interactions specifiques dans une hierarchie parent-enfant. - Le passage des donnees via les routes : Angular Router permet de transmettre des donnees entre les composants via les parametres de route (Route Parameters) ou en utilisant state dans la navigation. Cela est particulierement utile pour des applications multi-pages.
Dans ce tutoriel nous allons vous expliquer en detail comment etablir une communication efficace entre des composants parent et enfant dans une application Angular.
C'est quoi un Composant?
Un composant est une unite fondamentale d'une application Angular. Il s'agit d'une classe TypeScript qui permet d'encapsuler la logique ainsi que l'affichage d'une partie de l'application. Les composants permettent de structurer l'application en plusieurs parties reutilisables, chacune etant responsable d'une fonctionnalite ou d'une vue particuliere.
Maintenant revenons a notre sujet principale, la communication entre deux composants lies par la relation Parent- Enfant. Pour mettre cela en evidence, nous allons realiser une application permettant de simuler un panier d'achat avec des communications bidirectionnelles entres les composants. Notre futur application sera constituee de deux composants : Un composant parent qui affichera la liste des produits et un composant enfant dont le role sera d'afficher les produits du panier d'achat de l'utilisateur. L'utilisateur doit pouvoir ajouter ou supprimer un produit du panier.
Objectif:
- Creer un projet Angular
- Creer un composant Parent qui affichera la liste de produits disponibles.
- Creer un composant Enfant qui represente le panier et affichera les produits ajoutes.
- Etablir la communication entre le parent et l'enfant a travers les decorateurs
@Inputet@Output.
Creer un nouveau project Angular
Ouvrons notre terminal puis executons les commandes suivantes:
ng new panier-achat
cd panier-achat
La premiere commande initialise un projet Angular dans un nouveau repertoire nomme panier-achat. la seconde permet de se deplacer dans le repertoire du projet.
Creer nos composants
ng generate component product-list
ng generate component cart
Bravo nous venons de creer nos deux composants! Vous devez avoir cette structure si vous utilisez une version de Angular 14 ou superieure.
Maintenant passons aux choses serieuses: implementons notre premier composant product-list.
// panier-achat/src/app/product-list/product-list.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'product-list',
standelone: true,
imports: [],
templateUrl: './product-list.component.html',
styleUrl: './product-list.component.scss',
})
export class ProductListComponent {
produits = [
{ id: 1, nom: 'Produit A', prix: 20 },
{ id: 2, nom: 'Produit B', prix: 80 },
{ id: 3, nom: 'Produit C', prix: 30 },
{ id: 4, nom: 'Produit D', prix: 48 },
{ id: 5, nom: 'Produit E', prix: 209 },
]
panierProduits: any[] = [];
addToCart(produit: any): void {
this.panierProduits.push(produit);
}
}
<!-- panier-achat/src/app/product-list/product-list.component.html -->
<div>
<h1>Liste des Produits</h1>
<table>
<thead>
<tr>
<th>#</th>
<th>Nom</th>
<th>Prix</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@for (produit of panierProduits; track item.id) {
<tr>
<td>{{produit.id}}</td>
<td>{{produit.nom}}</td>
<td>{{produit.prix}} $</td>
<td>
<button (click)="addToCart(produit)">+ Ajouter</button>
</td>
</tr>
}
</tbody>
</table>
</div>
Super! nous venons d'ajouter une logique a notre composant. j'imagine que vous vous posez beaucoup de questions sur ce code!
Eh bien, je vous explique:
Dans le premier code : le fichier panier-achat/src/app/product-list/product-list.component.ts
- Le decorateur
@Componentdefinit le composant - Le selecteur
selectordefinit la balise HTML qui sera utiliser pour afficher le composant dans une page. standeloneintroduit depuis Angular 14, cet attribut avec la valeur atruepermet que le composant puisse fonctionner sans etre au sein d'un module. Si la valeur est afalse, le composant ne pourra etre afficher que s'il est importe dans un module.importscet attribut est un tableauJavaScriptdans lequel les modules et les composants enfants sont importes.templateUrlcelui-ci permet de specifier le chemin du fichier HTML qui s'occupe du rendu du composant.styleUrlpermet de specifier le chemin du fichier de style (.css, .scss, .sass, etc..) du composant.- Les lignes 12 a 18 nous declarons la variable produits, puis nous l'initialisons avec une liste de produits.
- La ligne 19 nous declarons la variable panierProduits, un tableau initialement vide dans lequel nous allons ajouter les produits selectionnes par l'utilisateur.
- Aux lignes 21 a 23 nous definissons la methode addToCart qui prend en parametre un produit puis l'ajoute au panier de produits.
Maintenant passons au second code : le fichier panier-achat/src/app/product-list/product-list.component.html il s'agit du code HTML qui s'occupe du rendu de notre page Liste des Produits. A la ligne 14 nous iterons a travers la boucle for pour afficher la liste des produits. Les lignes 16, 17 et 18 nous affichons les proprietes du produit en utilisant ce qu'on l'interpolation (string interpolation en Anglais). Il est marque par {{nom_de_la_variable}}. Etant donne que ce tutoriel est base sur Angular 17 la syntaxe de la boucle for n'est pas la meme que dans les versions procedente (< 16). Pour ceux qui utilise une version inferieure ou egale a la version 16 de Angular, la syntaxe est la suivante :
<tr *ngFor="let produit of panierProduits">
<td>{{produit.id}}</td>
<td>{{produit.nom}}</td>
<td>{{produit.prix}} $</td>
<td>
<button (click)="addToCart(produit)">+ Ajouter</button>
</td>
</tr>
Eh bien!, sans plus tarder implementons le composant cart.
// panier-achat/src/app/cart/cart.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-panier',
standelone: true,
imports: [],
templateUrl: './cart.component.html',
styleUrl: './cart.component.scss'
})
export class CartComponent {
@Input() panierProduits: [];
@Output remove = new EventEmitter<number>();
removeItemToCart(index: number) {
this.remove.emit(index);
}
}
<!-- panier-achat/src/app/cart/cart.component.html -->
<div>
<ul>
@for (item of panierProduits; track item.id) {
<li>
<div>
<div>{{item.nom}} - {{item.prix}}$</div>
<div><button type="button" (click)="removeItemToCart($index)">-</button></div>
</div>
</li>
}
</ul>
</div>
Ah oui ! je sais je vous dois des explications!
Commencons par le fichier panier-achat/src/app/cart/cart.component.ts.
- Ligne 12 : la variable panierProduits
-- Cette variable est un tableau qui contiendra les produits du panier. Grace au decorateur
@Input(), la valeur de cette variable sera fournie par le composant parent au moment de l'utilisation du composant CartComponent. -- Cela permet au composant CartComponent d'etre dynamique et reutilisable : son contenu est determine par les donnees passees depuis le composant parent. - Ligne 13 : l'evenement remove.
-- Le decorateur
@Output()transforme la variable remove en un emetteur d'evenements. -- Ce mecanisme permet au composant CartComponent d'envoyer des notifications vers le composant parent lorsqu'un produit est supprime. Le composant parent pourra alors gerer cette suppression. - Lignes 15 a 17 : la methode removeItemToCart
-- Cette methode est appelee lorsque l'utilisateur clique sur le bouton Supprimer dans le composant.
-- Elle utilise l'index passe en parametre pour emettre un evenement contenant cet index.
-- Grace a l'emetteur remove, le composant parent peut recevoir l'index de l'element a supprimer et effectuer l'action correspondante (comme retirer l'element du tableau partage).
Dans le second fichier,
panier-achat/src/app/cart/cart.component.htmla la ligne 8 nous avons la methoderemoveItemToCart($index)qui prend en parametre l'index du produit a supprimer du panier.
En appliquant du style Bootstrap a notre application, le resultat final est le suivant.

Vous pouvez tester le code final est disponible sur ce lien panier-achat.
Nous voila arrives a la fin de ce tutoriel ! J'espere qu'il vous a ete utile. Si c'est le cas, n'hesitez pas a le partager sur vos reseaux sociaux.
Merci et a bientot !
Track your progress
Sign in to resume reading later.