Angular 11 moderne : transmettre des données aux composants enfants avec input()

04 juil. 2026

Angular 11 moderne : transmettre des données aux composants enfants avec input()

Voici la leçon 11 du Cours d’Angular Moderne . Dans la leçon précédente, nous avons rendu une liste de produits en utilisant des signaux et `$(‘product’)` @for. Chaque carte affichait encore du contenu fictif. Il est maintenant temps de connecter les données réelles du composant parent au composant enfant en utilisant input()l’API moderne de signaux d’Angular.

Cet article fait partie de la série du Cours d’Angular Moderne . Consultez la page du cours pour voir la liste complète des épisodes.

Dans cet article, nous aborderons :

Le Modèle Mental

Avant d’écrire le moindre code, alignons le modèle :

Ceci est la communication classique entre parents et enfants, mais en utilisant des entrées modernes basées sur les signaux. C’est la première forme de communication entre composants que nous abordons dans ce cours.

Création d’une entrée obligatoire

Ouvrez product-card.ts et ajoutez une entrée obligatoire pour le produit :

import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { Product } from '../product';

@Component({
  selector: 'app-product-card',
  imports: [MatCardModule, MatButtonModule],
  templateUrl: './product-card.html',
  styleUrl: './product-card.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductCard {
  readonly product = input.required<Product>();
}

La phrase-clé :

readonly product = input.required<Product>();

Et voici ce que cela signifie :

  1. input.requiredmarque cette entrée comme obligatoire
  2. <Product>nous donne une typage strict
  3. L’entrée est basée sur un signal, donc on la lit avecproduct()

Si le composant parent oublie de passer ce paramètre, Angular nous avertira lors de la compilation et lors de l’exécution — exactement ce que nous voulons pour des données critiques.

Le décorateur @Input() Hérité

Si vous analysez des codes sources ou des tutoriels plus anciens d’Angular, vous trouvez fréquemment des entrées écrites sous cette forme :

import { Component, Input } from '@angular/core';
import { Product } from '../product';

export class ProductCard {
  @Input({ required: true }) product!: Product;
}

C’est l’approche basée sur les décorateurs qui était la norme avant Angular v17.

Les principales différences par rapport à l’API moderne input() :

Les deux syntaxes fonctionnent actuellement dans Angular, mais la syntaxe basée sur les signaux @Input()est obsolète et l’équipe Angular indique son retrait potentiel dans la version 22. La syntaxe basée sur les signaux input()est l’approche recommandée pour tout nouveau code, et c’est celle que nous utiliserons tout au long de ce cours.

Rendu des données d’entrée dans le modèle

Maintenant, remplaçons le contenu simulé du modèle de la carte par des données réelles.

Fichier :product-card.html

<mat-card class="product-card">
  <mat-card-header>
    <mat-card-title>{{ product().name }}</mat-card-title>
    <mat-card-subtitle>Product</mat-card-subtitle>
  </mat-card-header>

  <mat-card-content>
    <p>{{ product().description }}</p>
    <p class="price">{{ product().price | currency }}</p>
  </mat-card-content>

  <mat-card-actions>
    <button matButton>Add to Cart</button>
  </mat-card-actions>
</mat-card>

Notez que nous appelons `product()` dans le modèle. Cela se produit parce que `input()` retourne un signal d’entrée, et les signaux se lisent avec des parenthèses — la même règle que nous avons utilisée depuis la leçon 5.

Transfert des données du parent vers l’enfant

À présent, nous connectons le modèle parent à l’entrée de l’enfant.

Fichier :products-grid.html

<div class="products-grid">
  @for (product of products(); track product.id) {
    <app-product-card [product]="product"></app-product-card>
  } @empty {
    <div class="empty-state">
      <h3>No products available</h3>
      <p>Check back later for new arrivals!</p>
    </div>
  }
</div>

Le maillon qui relie tout :

[product]="product"

Le côté gauche représente le nom du champ d’entrée du composant enfant. Le côté droit représente la variable de boucle du composant parent. Désormais, chaque instance de ProductCard reçoit un objet produit de la liste.

Entrées optionnelles avec valeurs par défaut

Les champs obligatoires conviennent parfaitement pour des données essentielles, comme [exemple de données] product. Mais parfois, nous voulons un comportement configurable qui peut recourir à une valeur par défaut.

Nous allons ajouter un champ d’entrée optionnel pour contrôler le texte de l’étiquette du bouton.

Fichier :product-card.ts

import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { Product } from '../product';

@Component({
  selector: 'app-product-card',
  imports: [MatCardModule, MatButtonModule],
  templateUrl: './product-card.html',
  styleUrl: './product-card.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductCard {
  readonly product = input.required<Product>();
  readonly addButtonLabel = input('Add to Cart');
}

Ici, input('Add to Cart') signifie :

Maintenant, mettons à jour le modèle pour l’utiliser :

Fichier :product-card.html

<mat-card class="product-card">
  <mat-card-header>
    <mat-card-title>{{ product().name }}</mat-card-title>
    <mat-card-subtitle>Product</mat-card-subtitle>
  </mat-card-header>

  <mat-card-content>
    <p>{{ product().description }}</p>
    <p class="price">{{ product().price | currency }}</p>
  </mat-card-content>

  <mat-card-actions>
    <button matButton>{{ addButtonLabel() }}</button>
  </mat-card-actions>
</mat-card>

Et si vous souhaitez remplacer le texte du bouton par celui du composant parent :

<app-product-card [product]="product" [addButtonLabel]="'View Details'"></app-product-card>

Cela rend le composant encore plus réutilisable sans complexité supplémentaire.

Pièges courants

Deux erreurs typiques à éviter :

  1. Oublier les parenthèses dans le modèle — écrireproduct.name au lieu de product().name. Comme les entrées sont des signaux, il faut les appeler avec () pour lire la valeur.
  2. Marquer des données cruciales comme optionnelles alors qu’elles devraient être obligatoires — si le composant ne fonctionne pas sans une donnée, utilisez input.required<T>(). Si c’est une configuration avec une valeur par défaut adéquate, utilisez input(defaultValue).

Une bonne règle :

Code source

Le code source complet du cours est disponible sur GitHub : loiane/modern-angular .

Prochaine étape

Dans la prochaine leçon, nous approfondirons ce concept en ajoutant une interface utilisateur conditionnelle sur la carte, en utilisant @if et @else pour afficher des prix promotionnels et des étiquettes.

Regardez la vidéo

Cet article fait partie de la série du Cours d’Angular Moderne . Consultez la page du cours pour voir la liste complète des épisodes.

 

 

Fabien Delpont

Auteur

Fabien Delpont

Fabien Delpont, développeur et créateur du site Python Doctor.