Skip to content

Comment utiliser @ContentChild sur Angular ?

@ContentChild est un décorateur Angular qui permet de récupérer une référence à un enfant de contenu d'un composant. Vous pouvez l'utiliser pour accéder à un élément HTML ou à une directive présente dans le contenu transcluded (inclus) d'un composant.

Voici un exemple de code montrant comment utiliser @ContentChild :

ts
import { Component, ContentChild, ElementRef, AfterContentInit } from '@angular/core';

@Component({
  selector: 'app-my-component',
  standalone: true,
  template: `
    <ng-content></ng-content>
  `
})
export class MyComponent implements AfterContentInit {
  @ContentChild('myElement') myElement!: ElementRef;

  ngAfterContentInit() {
    console.log(this.myElement);
  }
}

Dans cet exemple, nous avons déclaré une référence de contenu appelée myElement qui référence l'élément HTML portant l'attribut #myElement. Dans la méthode ngAfterContentInit, nous pouvons accéder à l'élément en utilisant this.myElement.

Pour utiliser ce composant, nous pouvons inclure du contenu dans le template de notre composant parent, comme ceci :

html
<app-my-component>
  <div #myElement>Contenu inclus</div>
</app-my-component>

En utilisant @ContentChild, vous pouvez accéder à tous les éléments et directives inclus dans le contenu transcluded de votre composant, ce qui peut être utile pour réaliser des opérations sur ces éléments ou directives.

Exemple concret

Supposons que vous avez un composant MyButton qui affiche un bouton et qui prend en entrée un titre de bouton à afficher en utilisant une propriété de liaison de données. Maintenant, supposons que vous souhaitez utiliser ce composant MyButton dans un autre composant, mais que vous souhaitiez ajouter une icône avant le titre du bouton. Vous pouvez utiliser @ContentChild pour réaliser cette opération. Voici comment le code du composant parent pourrait ressembler :

ts
import { Component } from '@angular/core';
import { MyButtonComponent } from './my-button.component';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [MyButtonComponent],
  template: `
    <app-my-button>
      <i class="material-icons" #buttonIcon>favorite</i>
      {{ buttonTitle }}
    </app-my-button>
  `
})
export class MyComponent  {
  buttonTitle = 'Mon bouton';
}
ts
import { Component, Input, ContentChild, ElementRef, AfterContentInit } from '@angular/core';

@Component({
  selector: 'app-my-button',
  standalone: true,
  template: `
    <ng-content></ng-content>
  `
})
export class MyButtonComponent implements AfterContentInit { 
  @ContentChild('buttonIcon') buttonIcon!: ElementRef;

  ngAfterContentInit() {
    console.log(this.buttonIcon);
  }
}

Dans ce code, nous avons un composant MyButton qui affiche un bouton avec un titre et une icône. Le composant parent MyComponent utilise MyButton et inclut une icône et un titre dans le contenu "transcluded" du composant MyButton. En utilisant @ContentChild, nous pouvons accéder à l'icône et au titre inclus dans le contenu "transcluded" et réaliser des opérations sur eux, comme les afficher ou les modifier.

transcluded

Le terme "transcluded" fait référence au contenu inclus dans un composant parent et rendu dans le template du composant enfant. Cela permet d'inclure du contenu dynamique dans un composant sans avoir à le définir explicitement dans le template du composant enfant.