1. @Input – Passer des données du parent à l’enfant
Le truc sympa avec le décorateur @Input, c’est qu’il te permet de créer une sorte de pont à sens unique entre les données d’un composant parent et celles d’un composant enfant. C’est vraiment utile pour passer des données de l’un à l’autre, et ça garantit que ton flux de données reste clair et facile à comprendre.
Étape 1 : Crée le composant enfant
Pour créer un composant enfant, utilise la commande Angular CLI suivante:
ng generate component enfant.
Cette commande générera un nouveau composant nommé EnfantComponent avec les fichiers correspondants.
Étape 2 : Importe Input et crée la propriété @Input
Dans le fichier du composant enfant (enfant.component.ts), importe le décorateur Input depuis le module @angular/core. Ensuite, utilise le décorateur @Input() pour décorer la propriété que tu veux récupérer depuis le composant parent. Par exemple, si tu veux recevoir un objet qui représente un utilisateur :
import { Component, Input } from ‘@angular/core’;
@Component({
selector: ‘app-enfant’,
templateUrl: ‘./enfant.component.html’,
styleUrls: [‘./enfant.component.scss’]
})
export class EnfantComponent {
@Input() utilisateur: { nom: string, age: number };
}
Dans cet exemple, tu attends un objet utilisateur qui a deux propriétés : le nom et l’âge.
Étape 3 : Déclare la propriété à transmettre dans le composant parent
Dans le composant parent, déclare la propriété que tu veux envoyer au composant enfant. Par exemple, dans le fichier TypeScript du composant parent, ça ressemblerait à ça :
<!— parent.component.ts
déclare un objet utilisateur : —->
export class ParentComponent {
parentUtilisateur = { nom: ‘Alice’, age: 30 };
}
Étape 4 : Envoie les données depuis le composant parent
Dans le fichier HTML du composant parent (parent.component.html), lie la propriété que tu veux passer au composant enfant en utilisant la syntaxe de liaison de propriété.
<!– Fichier HTML du composant parent –>
<app-enfant [utilisateur]= »parentUtilisateur »></app-enfant>
Dans l’exemple ci-dessus, la propriété parent Utilisateur du composant parent est passée au composant enfant comme propriété utilisateur.
Étape 5 : Utilise les données reçues dans le composant enfant
Maintenant que le composant enfant a bien reçu les données, tu peux les utiliser dans le fichier HTML du composant enfant en utilisant la syntaxe d’interpolation ou dans le fichier TypeScript pour la logique du composant.
<!– Fichier HTML du composant enfant –>
<p>Nom de l’utilisateur : {{ utilisateur.nom }}</p>
<p>Age de l’utilisateur : {{ utilisateur.age }}</p>
Étape 6 : Utilise OnChanges pour détecter les modifications
Si tu as besoin de voir quand la propriété @Input change, implémente l’interface OnChanges et la méthode ngOnChanges() dans le composant enfant. Importe OnChanges et SimpleChanges depuis @angular/core.
import { Component, Input, OnChanges, SimpleChanges } from ‘@angular/core’;
@Component({
selector: ‘app-enfant’,
templateUrl: ‘./enfant.component.html’,
styleUrls: [‘./enfant.component.scss’]
})
export class EnfantComponent implements OnChanges {
@Input() utilisateur: { nom: string, age: number };
ngOnChanges(changes: SimpleChanges) {
if (changes.utilisateur) {
console.log(‘Changement détecté :’, changes.utilisateur);
// Tu peux effectuer des opérations supplémentaires en réponse aux changements ici.
}
}
}
Dans cet exemple, la méthode ngOnChanges() est appelée chaque fois que la propriété utilisateur change. L’objet changes contient des informations sur les modifications apportées à chaque propriété @Input.
Étape 7 : Ajoute des alias pour les propriétés @Input
Si tu veux donner un autre nom à la propriété @Input dans le composant enfant, tu peux utiliser un alias. Par exemple, si tu veux que la propriété soit appelée data dans le composant enfant, tu peux faire comme ça :
@Input(‘utilisateur’) data: { nom: string, age: number };
Maintenant, la propriété utilisateur du composant parent sera liée à la propriété data du composant enfant.
Étape 8 : Utilise des interfaces pour définir les types de données
Pour que ton code soit plus lisible et plus facile à entretenir, je te conseille d’utiliser des interfaces pour définir les types de données que tu passes avec @Input. Par exemple, tu peux créer une interface Utilisateur comme suit :
// utilisateur.interface.ts
export interface Utilisateur {
nom: string;
age: number;
}
// Puis, importe et utilise cette interface dans le composant enfant:
import { Utilisateur } from ‘../interfaces/utilisateur.interface’;
export class EnfantComponent implements OnChanges {
@Input() utilisateur: Utilisateur;
}
En suivant ces étapes détaillées, tu pourras facilement passer des données du composant parent au composant enfant en utilisant le décorateur @Input, tout en assurant un code clair et maintenable.
2. @Output – Renvoyer des données de l’enfant au parent
Le décorateur @Output est génial ! Il te permet de créer un lien à sens unique pour envoyer des données du composant enfant vers le composant parent en utilisant des événements personnalisés. C’est vraiment pratique pour transmettre des informations entre les composants tout en maintenant un flux de données bien clair et facile à comprendre.
Étape 1 : Importe Output et EventEmitter
Dans le fichier du composant enfant (enfant.component.ts), importe les décorateurs Output et EventEmitter depuis le module @angular/core:
import { Component, Output, EventEmitter } from ‘@angular/core’;
Étape 2 : Utilise le décorateur @Output et crée un EventEmitter
Décore la propriété que tu souhaites envoyer au composant parent avec le décorateur @Output() et instancie un nouvel EventEmitter. Par exemple, si tu souhaites envoyer un événement contenant un message :
@Component({…})
export class EnfantComponent {
@Output() messageEnvoye = new EventEmitter<string>();
}
Dans cet exemple, nous avons créé un EventEmitter de type string appelé messageEnvoye.
Étape 3 : Émets un événement avec la méthode emit()
Lorsque tu souhaites envoyer des données au composant parent, utilise la méthode emit() pour déclencher l’événement. Par exemple, si tu as un bouton qui envoie un message au composant parent :
envoyerMessage() {
this.messageEnvoye.emit(‘Bonjour, parent !’);
}
Étape 4 : Écoute l’événement dans le composant parent
Dans le fichier HTML du composant parent (parent.component.html), utilise la syntaxe de liaison d’événement pour écouter l’événement personnalisé émis par le composant enfant.
<!– Fichier HTML du composant parent –>
<app-enfant (messageEnvoye)= »recevoirMessage($event) »></app-enfant>
Dans l’exemple ci-dessus, tu écoutes l’événement messageEnvoye et appelle la méthode recevoirMessage() dans le composant parent lorsque l’événement est déclenché.
Étape 5 : Traite les données reçues dans le composant parent
Crée une méthode dans le fichier TypeScript du composant parent (parent.component.ts) pour traiter les données reçues lors de la réception de l’événement.
export class ParentComponent {
recevoirMessage(message: string) {
console.log(‘Message reçu du composant enfant :’, message);
}
}
Dans cet exemple, la méthode recevoirMessage() affiche le message reçu dans la console.
Étape 6 : Utilise des interfaces pour définir les types de données
Tout comme avec @Input, il est recommandé d’utiliser des interfaces pour définir les types de données émises via @Output. Par exemple, si tu envoies un objet Utilisateur défini précédemment :
import { Utilisateur } from ‘../interfaces/utilisateur.interface’;
export class EnfantComponent {
@Output()
Étape 7 : Détecte et gère plusieurs événements
Dans certains cas, tu pourras avoir besoin de gérer plusieurs événements émis par le composant enfant. Par exemple, tu peux créer deux EventEmitters pour différents types d’événements :
@Output() ajoutUtilisateur = new EventEmitter<Utilisateur>();
@Output() suppressionUtilisateur = new EventEmitter<Utilisateur>();
Dans le composant parent, tu peux écouter ces événements séparément :
Exemple de html:
<app-enfant
(ajoutUtilisateur)= »gererAjoutUtilisateur($event) »
(suppressionUtilisateur)= »gererSuppressionUtilisateur($event) »
></app-enfant>
Puis, défini les méthodes correspondantes dans le fichier TypeScript du composant parent (parent.component.ts) pour traiter les données reçues lors de la réception des événements.
Étape 8 : Utilise des services pour une communication complexe
Effectivement, lorsque la communication entre les composants devient plus complexe et difficile à gérer avec @Input et @Output, il est judicieux d’envisager l’utilisation de services Angular pour partager des données et des événements entre les composants. Les services offrent une approche plus flexible et maintenable pour gérer la communication entre les composants.
En suivant les étapes détaillées que nous avons couvertes précédemment, tu seras en mesure d’envoyer facilement des données du composant enfant vers le composant parent en utilisant le décorateur @Output. Cela t’aidera à maintenir un code clair et facile à gérer. Cependant, si les besoins en communication deviennent plus complexes, je te recommande vivement d’explorer l’utilisation des services Angular.
Les services permettent de centraliser la logique de communication et de partager des données et des événements entre les composants de manière plus souple. Cela améliore la maintenabilité de ton code et te donne une plus grande flexibilité dans la gestion de la communication entre les composants.
3. Bonnes pratiques
Utiliser correctement @Input et @Output est essentiel pour garantir un code clair, maintenable et évolutif.
1. Utilise des interfaces pour définir les types de données
Il est recommandé d’utiliser des interfaces pour définir les types de données passées via @Input et émises via @Output. Cela améliore la lisibilité, la maintenabilité et facilite la détection d’erreurs lors du développement.
// utilisateur.interface.ts
export interface Utilisateur {
nom: string;
age: number;
}
2. Utilise des alias pour les propriétés @Input et @Output
Dans certains cas, tu souhaites peut-être donner un nom différent à la propriété @Input ou @Output dans le composant enfant. Tu pourras utiliser des alias pour éviter les conflits de noms et rendre le code plus lisible.
@Input(‘parentData’) enfantData: Utilisateur;
@Output(‘enfantEvent’) parentEvent = new EventEmitter<string>();
3. Implémente l’interface OnChanges pour détecter les modifications
Lorsque tu dois détecter et réagir aux modifications des propriétés @Input, implémente l’interface OnChanges et la méthode ngOnChanges() dans le composant enfant. Cela te permet de suivre les changements et d’effectuer des actions supplémentaires en réponse.
import { Component, Input, OnChanges, SimpleChanges } from ‘@angular/core’;
@Component({…})
export class EnfantComponent implements OnChanges {
@Input() utilisateur: Utilisateur;
ngOnChanges(changes: SimpleChanges) {
if (changes.utilisateur) {
console.log(‘Changement détecté :’, changes.utilisateur);
}
}
}
4. Utilise des services
Lorsque la communication entre les composants devient complexe, il est préférable d’utiliser des services Angular pour partager des données et des événements entre les composants. Les services offrent une approche plus flexible et maintenable pour gérer la communication entre les composants.
// shared.service.ts
import { Injectable } from ‘@angular/core’;
import { BehaviorSubject } from ‘rxjs’;
@Injectable()
export class SharedService {
private messageSource = new BehaviorSubject<string>(‘message initial’);
currentMessage = this.messageSource.asObservable();
changeMessage(message: string) {
this.messageSource.next(message);
}
}
5. Évite une communication bidirectionnelle excessive
Il est important de maintenir un flux de données unidirectionnel pour éviter la complexité et les erreurs potentielles. Si tu trouves que tu as besoin de trop de communication bidirectionnelle entre les composants parent et enfant, envisage de revoir ton architecture et d’utiliser des services pour simplifier la communication.
6. Utilise la syntaxe de liaison de propriétés et d’événements
Assure-toi d’utiliser la syntaxe de liaison de propriétés et d’événements correcte pour les propriétés @Input et @Output. Cela garantit que ton code suit les meilleures pratiques Angular et est facile à comprendre.
Exemple pour @Input :
<!– Fichier HTML du composant parent –>
<app-enfant [utilisateur]= »parentUtilisateur »></app-enfant>
Exemple pour @Output :
<!– Fichier HTML du composant parent –>
<app-enfant (messageEnvoye)= »recevoirMessage($event) »></app-enfant>
7. Utilise des noms de variables et d’événements clairs
Assure-toi que les noms des variables et des événements sont clairs et reflètent leur fonction. Cela permet aux autres développeurs de comprendre rapidement le code et facilite la maintenance du code.
// Composant enfant
@Input() utilisateur: Utilisateur;
@Output() utilisateurSelectionne = new EventEmitter<Utilisateur>();
8. Sépare les responsabilités entre les composants
Chaque composant doit avoir une responsabilité unique et claire. Essaye de ne pas surcharger un composant avec plusieurs responsabilités, et préfère créer des composants plus petits et réutilisables. Cela améliore la maintenabilité et la compréhension du code.
9. Utilise des modificateurs d’accès appropriés
Utilise des modificateurs d’accès appropriés pour les propriétés @Input et @Output. En général, les propriétés @Input et @Output doivent être déclarées comme public pour qu’elles soient accessibles depuis le composant parent.
10. Teste les liaisons @Input et @Output
Absolument ! Il est essentiel de tester les liaisons @Input et @Output pour s’assurer que la communication entre les composants fonctionne correctement. Pour cela, tu peux utiliser des frameworks de test comme Jasmine et des outils de test Angular tels que TestBed.
En écrivant et en exécutant des tests unitaires pour tes composants, tu peux vérifier si les données sont correctement transmises via les liaisons @Input et si les événements sont correctement émis via les liaisons @Output. Cela te permet de garantir que ton code Angular est clair, maintenable et évolutif.
Les tests unitaires te donnent la confiance nécessaire pour valider le bon fonctionnement de ton code et détecter d’éventuels problèmes de communication entre les composants. Cela contribue à la qualité globale de ton application Angular.
Veille à suivre ces bonnes pratiques et à effectuer des tests approfondis pour tes liaisons @Input et @Output. Cela t’aidera à maintenir un code solide et fiable, tout en exploitant efficacement les décorateurs @Input et @Output pour la communication entre les composants.