20-2 Observer les changements d'un @Input
Tout semble bien aller pour l'instant. Cependant, si lors de l'initialisation vous récupérez de l'information sur laquelle votre composant est dépendant, cependant, imaginez que vous effectuez une requête d'API via votre service pour récupérer l'information:
export class IssuesListe implements OnInit {
@Input() projetId: number | null = null;
async ngOnInit() {
await this.chargerIssues()
}
async chargerIssues() {
// Ici, on appelerait plutôt un service `IssueService` pour récupérer les issues du projet
console.log('Chargement des issues pour le projet:', this.projetId);
}
}
Ouvrez la console de votre navigateur, et utilisez le menu de projets pour changer de projet:
Dans l'animation ci-haut, le id du projet affiché change, mais pas l'info affichée dans la console!
Il s'agit d'un problème similaire à celui du changement d'URL qui nous force à devoir observer les changements à l'URL. Cependant, il ne s'agit pas ici d'observer l'URL, mais plutôt l'entrée @Input
du composant.
En effet, issues-liste
sait que l'identifiant du projet a changé, mais ne repasse pas par l'initialisation du composant puisqu'il est déjà initialisé!
Implémenter ngOnChanges
Pour observer les changements, il faut implémenter la fonction ngOnChanges
.
Implémentez l'interface OnChanges
dans issues-liste
:
export class IssuesListe implements OnInit, OnChanges {
@Input() projetId: number | null = null;
async ngOnInit() {
await this.chargerIssues()
}
ngOnChanges(changes: SimpleChanges): void {
throw new Error('Method not implemented.');
}
async chargerIssues() {
// Ici, on appelerait plutôt un service `IssueService` pour récupérer les issues du projet
console.log('Chargement des issues pour le projet:', this.projetId);
}
}
Réagir aux changements
la fonction ngOnChanges
est appelée chaque fois qu'il y a un changement à un Input
. L'argument changes
de type SimpleChanges
est un tableau dont les clés sont les noms de variable des Input
.
Par exemple, pour savoir lorsque projetId
changé:
ngOnChanges(changes: SimpleChanges): void {
if(changes['projetId']) {
// ... action lorsque `projetId` a changé
}
}
Et ainsi, on pourrait "rafraichir la liste d'issues" (console.log ici :))
du même coup:
async ngOnChanges(changes: SimpleChanges) {
if(changes['projetId']) {
await this.chargerIssues();
}
}
Assurez-vous de modifier la fonction pour une fonction async
Voilà! Maintenant, lorsque vous changez de projet via le menu principal, vous êtes en mesure d'être notifié et de répondre aux changements! 🙂
Ne pas réagir au premier changement
Si vous observez, au premier chargement de la page, vous verrez deux console.log
:
C'est que la première assignation du Input
est elle-même détectée comme un changement. Donc, les issues se trouvent à être chargées lors du chargement initial dans ngOnInit
, mais aussi dans ngOnChanges
.
Pour ne pas réagir au premier changement et laisser le soin à ngOnInit
de faire son travail, on peut détecter qu'il ne s'agit pas du premier changement dans ngOnChanges
de cette façon:
async ngOnChanges(changes: SimpleChanges) {
if(changes['projetId'] && !changes['projetId'].firstChange) {
await this.chargerIssues();
}
}
De cette façon, cela ne créera pas deux appels d'API au chargement! 🙂