Skip to content

Instantly share code, notes, and snippets.

@sDromacque
Last active February 5, 2026 13:33
Show Gist options
  • Select an option

  • Save sDromacque/4105fdcaece3184a9f91bb99fe6a09b2 to your computer and use it in GitHub Desktop.

Select an option

Save sDromacque/4105fdcaece3184a9f91bb99fe6a09b2 to your computer and use it in GitHub Desktop.
Signal input

🚀 1. Qu’est‑ce qu’un Signal Angular ?

Un signal est une valeur réactive synchronisée, qui :

  • stocke une valeur
  • notifie ses dépendants dès qu’elle change
  • se lit comme une fonction : mySignal()

Exemple :

const count = signal(0);
count();   // lecture
count.set(1); // écriture

👉 C’est simple, prévisible, et synchrone.
Pas d’abonnements, pas d’async pipe, pas de zones, pas de rebond inutile.


🔥 2. Les trois types de primitives Signals

✔️ signal() — une valeur modifiable

const name = signal("Seb");
name.set("Sébastien");

✔️ computed() — une valeur dérivée

const fullname = computed(() => `${firstname()} ${lastname()}`);

✔️ effect() — un side‑effect quand un signal change

effect(() => console.log("Count changed:", count()));

🎯 3. Le signal input() : LE nouveau paradigme pour @Input

input() remplace @Input() par un signal d’entrée, fourni par le parent.

Exemple simple :

readonly user = input<User>();

⚠️ Important :
Les valeurs provenant de input() sont READONLY (conceptuellement).


🧠 4. Comment Angular veut que tu raisonnes avec input()

Quand tu écris :

readonly addresses = input<Addresses>();

Cela veut dire :

  • le parent contrôle la donnée
  • le composant lit la donnée
  • le composant ne la modifie jamais

C’est un contrat clair :
➡️ input = source externe, jamais modifiée
➡️ signal = source interne modifiable

C’est LE point le plus souvent mal compris.


💥 5. Les interdits absolus avec input()

❌ 1. Ne jamais écrire dessus :

this.addresses.set(...)

❌ 2. Ne jamais muter son contenu :

this.addresses().city = "Paris"; 

➡️ Pourquoi ?

  • dirty detection impossible
  • template ne se met pas à jour
  • mutation silencieuse
  • violation du contrat parent → enfant
  • débogage infernal assuré

⭐ 6. Comment travailler correctement avec input()

✔️ A. Lire la valeur

Toujours :

const a = this.addresses();

✔️ B. Créer des computed dérivés

Méthode recommandée Angular :

readonly shippingAddress = computed(() =>
  this.addresses()?.shippingAddress ?? null
);

✔️ C. Si tu DOIS modifier → copie locale !

readonly addresses = input<Addresses>();

private localAddresses = signal<Addresses>(new Addresses());

effect(() => {
  const incoming = this.addresses();
  if (incoming) {
    this.localAddresses.set(structuredClone(incoming));
  }
});

Puis :

this.localAddresses.mutate(a => {
  a.shippingAddress = ...
});

🌟 7. Faut‑il mettre un default dans input() ?

Oui, mais intelligemment.

✔️ Recommandé :

readonly addresses = input<Addresses>(() => new Addresses());

➡️ Factory pure, aucune mutation partagée, propre.

❌ À éviter :

readonly addresses = input<Addresses>(new Addresses());

➡️ Passe la même instance partout → piège de mutabilité.


🩻 8. Pourquoi les Signals sont meilleurs que @Input classique ?

Avec @Input :

  • pas de réactivité fine
  • pas de dérivations simples
  • change detection imprévisible
  • besoin de lifecycle hooks
  • type‑narrowing fragile

Avec input() :

  • réactivité fine‑grainée
  • lecture simple user()
  • valeurs dérivées en computed()
  • aucune magie
  • predictable flow
  • code plus propre et plus testable

🧨 9. Le plus gros piège des Signals : la mutabilité

Le signal ne déclenche rien si tu modifies l’objet interne :

const user = signal({name: "Seb"});
user().name = "Sébastien"; // ❌ → effect ne détecte rien

Pourquoi ?
➡️ parce que le signal observe la référence, pas le contenu.

📌 Toujours utiliser set() ou update() pour les signaux modifiables.


🏆 10. Résumé ultime

Concept À faire À ne pas faire
lecture addresses() addresses
modification set/update/mutate (mais pas sur un input) mutation directe
input() readonly, non modifié modifié, muté, remplacé
default value factory () => new Value() new Value() directement
template capturer dans une const locale appeler 10 fois signal()

🎁 Bonus : modèle parfait pour un composant moderne

readonly addresses = input<Addresses>();

readonly shippingAddress = computed(() => {
  const a = this.addresses();
  return a?.shippingAddress ?? this.legalUnit?.address ?? null;
});

Template :

Clair. Lisible. Zéro mutation. Zéro bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment