Angular
Projection & Composants

La Poupée Russe (Composant projeté)

Nous avons vu contentChild() pour récupérer une balise HTML. Mais si on l'utilise avec une classe, un Composant peut "pirater" un autre Composant qui a été glissé à l'intérieur de lui par le Parent. C'est l'architecture parfaite pour les systèmes de "Plugins" !

L'Architecte (Le Parent)

Le Parent assemble les pièces : Il insère le Module (Enfant 2) à l'intérieur du Serveur (Enfant 1).

Le Serveur (Enfant 1)
Héberge le module injecté
Emplacement du module (ng-content)
Connecté

L'ordre d'assemblage

  • 1. Le Parent crée l'imbrication<app-serveur> <app-module /> </app-serveur>
  • 2. Le Serveur scanne ses entrailles Dans le TypeScript du Serveur : plugin = contentChild(AppModuleClass). Il trouve le module projeté par le parent.
  • 3. Le Serveur prend le contrôle Le Serveur peut maintenant appeler des méthodes ou modifier des variables du Module. Exemple : this.plugin().statut = false.

Le Code Source Complet

import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <!-- J'insère Enfant 2 À L'INTÉRIEUR de Enfant 1 -->
    <app-enfant1>
      <app-enfant2></app-enfant2>
    </app-enfant1>
  `
})
export class ParentComponent {}
import { Component, contentChild } from '@angular/core';
import { Enfant2Component } from './enfant2.component';

@Component({
  selector: 'app-enfant1',
  template: `
    <div>
      <!-- L'Enfant 2 atterrit ici -->
      <ng-content></ng-content>

      <button (click)="togglePlugin()">Désactiver le plugin injecté</button>
    </div>
  `
})
export class Enfant1Component {
  // Je scanne mon intérieur pour trouver le composant Enfant 2
  plugin = contentChild(Enfant2Component);

  togglePlugin() {
    const module = this.plugin();
    if (module) {
      // Je modifie la propriété de l'enfant 2
      module.status = !module.status; 
    }
  }
}
import { Component } from '@angular/core';

@Component({
  selector: 'app-enfant2',
  template: `
    <span>{{ status ? 'Allumé' : 'Éteint' }}</span>
  `
})
export class Enfant2Component {
  // Une simple propriété publique
  status = true; 
}