Appearance
Comment utiliser viewChildren() sur Angular ?
Les requêtes de vue permettent d'accéder aux éléments définis dans le template d'un composant.
Utiliser les composants avec des signaux
Depuis Angular 17.x, les signaux sont introduits en tant que réactifs comme alternative aux décorateurs @Input()
, @Output()
, etc.
Donc, pour utiliser input()
, output()
, model()
, contentChild()
, contentChildren()
, viewChild()
et viewChildren()
, il est essentiel de comprendre la notion des signaux.
Lisez l'article sur les signaux pour en savoir plus.
Utiliser la fonction viewChildren()
Imaginons que vous ayez plusieurs paragraphes dans votre page et que vous souhaitiez pouvoir accéder à tous ces éléments. C'est exactement ce que permet viewChildren()
: accéder à plusieurs éléments enfants d'un composant.
Voici un exemple simple :
ts
import { Component, viewChildren, ElementRef } from '@angular/core';
@Component({
selector: 'app-demo',
standalone: true,
template: `
<p #paragraph>Premier paragraphe</p>
<p #paragraph>Deuxième paragraphe</p>
<p #paragraph>Troisième paragraphe</p>
<button (click)="showParagraphs()">Afficher les paragraphes</button>
`
})
export class DemoComponent {
// Récupère tous les éléments avec la référence #paragraph
paragraphs = viewChildren('paragraph');
showParagraphs() {
// Affiche le contenu de chaque paragraphe
this.paragraphs().forEach(p => {
console.log(p.nativeElement.textContent);
});
}
}
La fonction viewChildren()
retourne un signal contenant un tableau d'ElementRef
. Pour accéder aux éléments, il faut utiliser les parenthèses ()
pour obtenir la valeur du signal.
La syntaxe
#
est utilisée pour définir une "référence" dans le template. Une référence est une variable qui permet d'accéder à un élément du DOM ou d'un composant enfant.
Dans cet exemple :
- Nous avons trois paragraphes avec la même référence
#paragraph
viewChildren('paragraph')
nous permet de récupérer tous ces éléments- Nous pouvons ensuite accéder à chaque élément via la propriété
nativeElement
Accéder aux composants enfants
viewChildren()
permet d'accéder à plusieurs éléments qui correspondent à votre requête. C'est particulièrement utile pour les listes d'éléments :
ts
import { Component, viewChildren } from '@angular/core';
import { UserCardComponent } from './user-card.component';
@Component({
selector: 'app-user-list',
standalone: true,
imports: [UserCardComponent],
template: `
@for (user of users; track user.id) {
<app-user-card [user]="user" />
}
<button (click)="highlightAllUsers()">Mettre en évidence tous les utilisateurs</button>
`
})
export class UserListComponent {
users: User[] = [
{ id: 1, name: 'John Doe', username: 'johndoe', email: '[email protected]' },
{ id: 2, name: 'Jane Doe', username: 'janedoe', email: '[email protected]' }
];
// Accès à tous les composants UserCard
userCards = viewChildren(UserCardComponent);
highlightAllUsers() {
this.userCards().forEach(card => {
// Accès à chaque carte utilisateur
card.highlightUser();
});
}
}
ts
import { Component } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
template: `
<h1>User Card</h1>
`
})
export class UserCardComponent {
highlightUser() {
console.log('User Card');
}
}
Utiliser le décorateur @ViewChildren
Avant Angular 17
Le décorateur @ViewChildren
est la façon traditionnelle de définir des requêtes de vue dans Angular avant la version 17.
@ViewChildren
est une décorateur Angular qui vous permet de récupérer une référence à un ou plusieurs éléments enfants de votre vue. Vous pouvez l'utiliser de cette manière:
ts
import { Component, ViewChildren, QueryList, AfterViewInit, ElementRef } from '@angular/core';
@Component({
selector: 'app-my-component',
standalone: true,
template: `
<div #child1></div>
<div #child2></div>
`
})
export class MyComponent implements AfterViewInit {
@ViewChildren('child1, child2') children!: QueryList<ElementRef>;
ngAfterViewInit() {
console.log(this.children); // QueryList containing the two div elements
}
}
Dans cet exemple, nous avons utilisé @ViewChildren
pour récupérer une référence aux deux div
enfants de la vue. Le décorateur prend en paramètre une chaîne qui correspond aux noms des éléments cibles. Dans notre cas, nous avons utilisé des noms d'éléments, mais vous pouvez également utiliser des selecteurs de classes ou d'autres types de sélecteurs.
Le décorateur renvoie une instance de QueryList
, qui est une classe Angular qui représente une liste d'objets pouvant être observés. Vous pouvez utiliser les méthodes de QueryList
pour itérer sur les éléments de la liste ou pour vous abonner aux changements de la liste.
WARNING
Il est important de noter que @ViewChildren
ne sera disponible que lorsque la vue a été initialisée. Vous devrez donc attendre que le cycle de vie ngAfterViewInit
soit appelé pour accéder aux éléments enfants.
QueryList
QueryList
est une classe utilisée par Angular pour représenter une liste d'objets pouvant être observés. Elle est utilisée principalement avec les décorateurs de requête tels que @ViewChildren
et @ContentChildren
, qui permettent de récupérer une référence à des éléments enfants d'un composant ou d'une vue.
QueryList
possède plusieurs méthodes utiles pour itérer sur les éléments de la liste et pour s'abonner aux changements de la liste. Par exemple, vous pouvez utiliser .forEach()
pour itérer sur chaque élément de la liste, ou .changes
pour s'abonner aux changements de la liste. Vous pouvez également utiliser la propriété .length
pour obtenir le nombre d'éléments dans la liste.
Voici un exemple qui montre comment utiliser QueryList
pour itérer sur chaque élément de la liste et afficher leur contenu:
ts
import { Component, ViewChildren, QueryList, ElementRef, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-my-component',
standalone: true,
template: `
<div #child1>Content of child 1</div>
<div #child2>Content of child 2</div>
`
})
export class MyComponent implements AfterViewInit {
@ViewChildren('child1, child2') children!: QueryList<ElementRef>;
ngAfterViewInit() {
this.children.forEach((child) => {
console.log(child.nativeElement.textContent);
});
}
}
Dans cet exemple, ngAfterViewInit
est appelé une fois que la vue a été initialisée, et nous utilisons forEach
pour itérer sur chaque élément de la liste children
et afficher leur contenu.