Premiers pas avec les signaux Angular

1. Avant de commencer

Logo Angular noir

Les signaux Angular introduisent trois primitives réactives dans Angular que vous connaissez et appréciez, ce qui simplifie votre développement et vous permet de créer des applications plus rapides par défaut.

Objectifs de l'atelier

  • Vous découvrirez les trois primitives réactives introduites par les signaux angulaires: signal(), computed() et effect().
  • Utilisez les signaux Angular pour booster un jeu d'algorithmes de chiffrement. Les algorithmes de chiffrement permettent de chiffrer et de déchiffrer des données. Dans ce jeu, les utilisateurs peuvent décoder un message secret en faisant glisser des indices pour le résoudre, chiffrer le message et partager son URL avec ses amis.

Jeu Cypher Angular ressemblant à une console de jeu verte vintage, avec un message caché à l'écran : "Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!"

Prérequis

2. Obtenir le code

Tout ce dont vous avez besoin pour ce projet se trouve dans une pile Stackblitz. Nous vous recommandons d'utiliser Stackblitz pour cet atelier de programmation. Vous pouvez également cloner le code et l'ouvrir dans votre environnement de développement préféré.

Ouvrez Stackblitz et exécutez l'application.

Pour commencer, ouvrez le lien Stackblitz dans votre navigateur Web préféré:

  1. Ouvrez un nouvel onglet du navigateur et accédez à https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcrypt%2Fservice.encryption.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts.
  2. Dupliquez le Stackblitz pour créer votre propre espace de travail modifiable. Stackblitz devrait exécuter automatiquement l'application, et le tour est joué !

Autre solution: cloner le dépôt et diffuser l'application

L'utilisation de VSCode ou d'un IDE local est une autre méthode pour suivre cet atelier de programmation:

  1. Ouvrez un nouvel onglet du navigateur et accédez à https://github.com/linear/codelabs/tree/signals-get-started.
  2. Dupliquez et clonez le dépôt, puis utilisez la commande cd codelabs/ pour y accéder.
  3. Vérifiez la branche de code de démarrage avec la commande git checkout signals-get-started.
  4. Ouvrez le code dans VSCode ou dans l'IDE de votre choix.
  5. Pour installer les dépendances requises pour l'exécution du serveur, exécutez la commande npm install.
  6. Pour exécuter le serveur, utilisez la commande ng serve.
  7. Ouvrez http://localhost:4200 dans un nouvel onglet de votre navigateur.

3. Établir une référence

Votre point de départ est un jeu d'algorithme de chiffrement, mais il ne fonctionne pas encore. Les signaux Angular alimentent les fonctionnalités du jeu.

Jeu Cypher Angular ressemblant à une console de jeu verte vintage, avec un message caché à l'écran : "Anqnxaa Lpcnaxl aaf pn jfafxyofa aofapfm pn a16 wyjak!"

Pour commencer, parcourez la version finale de ce que vous allez développer: Angular Signals Cypher.

  1. Affichez le message codé à l'écran.
  2. Glissez-déposez sur le clavier un bouton représentant une lettre pour tenter de résoudre le chiffrement et de décoder le message secret.
  3. Si l'opération réussit, vous verrez comment le message sera mis à jour pour décoder davantage le message secret.
  4. Cliquez sur Personnaliser pour modifier l'expéditeur et le message, puis cliquez sur Créer et copier l'URL pour voir les valeurs à l'écran et la modification d'URL.
  5. Bonus: Copiez et collez l'URL dans un nouvel onglet ou partagez-la avec un ami. Vous verrez comment l'expéditeur et le message sont stockés dans l'URL.

GIF du jeu Cypher Angular, avec un message masqué décodé à l'écran qui indique "Les signaux Angular sont en version Preview développeur aujourd'hui dans la version 16".

4. Définir votre premier signal()

Un signal est une valeur qui peut indiquer à Angular lorsqu'il change. Certains signaux peuvent être modifiés directement, tandis que d'autres calculent leurs valeurs à partir de celles d'autres signaux. Ensemble, les signaux créent un graphe de dépendances dirigé qui modélise la manière dont les données circulent dans votre application.

Angular peut utiliser les notifications de signaux pour identifier les composants à détecter ou pour exécuter les fonctions d'effet que vous définissez.

Convertir superSecretMessage en signal()

superSecretMessage est une valeur MessageService qui définit le message secret que le joueur décode. Actuellement, la valeur n'informe pas l'application des modifications. Par conséquent, le bouton Customize (Personnaliser) ne fonctionne pas. Vous pouvez résoudre ce problème avec un signal.

En faisant de superSecretMessage un signal, vous pouvez avertir certaines parties de l'application qui dépendent de savoir quand le message a changé. Lorsque vous personnaliserez le message dans une boîte de dialogue, vous le configurerez pour mettre à jour le reste de l'application avec le nouveau message.

Pour définir votre premier signal, procédez comme suit sous le commentaire TODO(1): Define your first signal() dans chaque fichier:

  1. Dans le fichier service.message.ts, utilisez la bibliothèque de signaux pour rendre superSecretMessage réactif:

src/app/secret-message/service.message.ts

superSecretMessage = signal(
  'Angular Signals are in developer preview in v16 today!'
);

Cela vous invite automatiquement à importer signal depuis @angular/core. Si vous actualisez la page, vous rencontrerez probablement des erreurs, que vous avez mentionnées précédemment dans superSecretMessage. Cela est dû au fait que vous avez remplacé le type de superSecretMessage de string par SettableSignal<string>. Pour résoudre ce problème, modifiez toutes les références à superSecretMessage afin d'utiliser l'API Signals. Chaque fois que vous lisez la valeur, appelez le getter du signal superSecretMessage(). Lorsque vous écrivez la valeur, utilisez l'API .set sur SettableSignal pour définir la nouvelle valeur du message.

  1. Dans les fichiers secret-message.ts et service.message.ts, remplacez toutes les références de superSecretMessage par superSecretMessage():

src/app/secret-message/secret-message.ts

// Before
this.messages.superSecretMessage
this.messages.superSecretMessage = message;

// After
this.messages.superSecretMessage()
this.messages.superSecretMessage.set(message);

src/app/secret-message/service.message.ts

// Before
this.superSecretMessage

// After
this.superSecretMessage()

Explorer les deux autres signaux

  • Notez que votre application comporte deux autres signaux:

src/app/encryption/service.encryption.ts.

cipher = signal(this.createNewCipherKey());
decodedCipher = signal<CipherKey[]>([]);

La CipherService définit un signal cipher, un mappage généré aléatoirement de paires clé/valeur entre une lettre de l'alphabet et une nouvelle lettre cipher. Utilisez-le pour mélanger les messages et déterminer si le joueur détecte une correspondance réussie sur le clavier.

Vous obtenez également un signal decodedCipher des paires clé-valeur décodées avec succès. Vous les ajouterez lorsque le lecteur résoudrea l'algorithme de chiffrement.

L'attribut unique et puissant de la bibliothèque Signals d'Angular est que vous pouvez introduire de la réactivité partout. Vous avez défini des signaux une fois dans les services de l'application. Vous pouvez les utiliser dans un modèle, des composants, des pipelines, d'autres services ou partout où vous pouvez écrire du code d'application. Ils ne sont pas limités ou liés à un champ d'application de composant.

Vérifier les modifications

  • Il vous reste une dernière étape à effectuer avant que l'application fonctionne. Pour l'instant, essayez d'ajouter un console.log() dans différentes parties de votre application pour voir comment votre superSecretMessage est configuré.

Stackblitz avec un message console.log() indiquant que superSecretMessage consigne correctement le nouveau message.

5. Définir votre première "calcul()"

Dans de nombreux cas, vous pouvez dériver un état à partir de valeurs existantes. Il est préférable que l'état dérivé soit mis à jour lorsque la valeur dépendante change.

computed() vous permet d'exprimer un signal déclaratif qui tire sa valeur d'autres signaux.

Convertir solvedMessage en computed()

solvedMessage traduit la valeur secretMessage encodée en décodée à l'aide du signal decodedCipher.

C'est très pratique, car vous voyez que vous générez une valeur de calcul basée sur une autre valeur. Par conséquent, chaque fois qu'un signal dans ce contexte réactif mappé est modifié, les dépendances en sont informées.

Actuellement, l'élément solvedMessage n'est pas mis à jour lorsque vous modifiez secretMessage, decodedCipher ou superSecretMessage. Ainsi, vous ne verrez pas de mises à jour à l'écran lorsque le lecteur aura résolu le chiffrement.

En faisant de solvedMessage un calcul, vous créez un contexte réactif. Ainsi, lorsque vous mettez à jour le message ou résolvez le chiffrement, vous pouvez obtenir une mise à jour de l'état à partir des dépendances suivies.

Pour convertir solvedMessage en computed(), procédez comme suit sous le commentaire TODO(2): Define your first computed() de chaque fichier:

  1. Dans le fichier service.message.ts, utilisez la bibliothèque de signaux pour rendre solvedMessage réactif:

src/app/secret-message/service.message.ts

solvedMessage = computed(() =>
  this.translateMessage(
    this.secretMessage(),
    this.cipher.decodedCipher()
  )
);

Cela vous invite automatiquement à importer computed depuis @angular/core. Si vous actualisez la page, vous rencontrerez probablement des erreurs, que vous avez mentionnées précédemment dans solvedMessage. En effet, vous avez remplacé le type de superSecretMessage de string par Signal<string>, une fonction. Pour résoudre ce problème, remplacez toutes les références à solvedMessage par solvedMessage().

  1. Dans le fichier secret-message.ts, remplacez toutes les références de solvedMessage par solvedMessage():

src/app/secret-message/secret-message.ts

// Before
<span *ngFor="let char of this.messages.solvedMessage.split(''); index as i;" [class.unsolved]="this.messages.solvedMessage[i] !== this.messages.superSecretMessage()[i]" >{{ char }}</span>

// After
<span *ngFor="let char of this.messages.solvedMessage().split(''); index as i;" [class.unsolved]="this.messages.solvedMessage()[i] !== this.messages.superSecretMessage()[i]" >{{ char }}</span>

Notez que, contrairement à superSecretMessage, solvedMessage n'est pas un SettableSignal. Vous ne pouvez pas modifier sa valeur directement. Sa valeur est mise à jour chaque fois que ses signaux de dépendance (secretMessage et decodedCipher) sont mis à jour.

Explorer les deux autres fonctions computed()

  • Notez que votre application contient deux autres valeurs calculées:

src/app/secret-message/service.message.ts

secretMessage = computed(() =>
  this.translateMessage(
    this.superSecretMessage(),
    this.cipher.cipher()
  )
);

src/app/encryption/service.encryption.ts.

unsolvedAlphabet = computed(() =>
  ALPHABET.filter(
    (letter) => !this.decodedCipher().find((guess) => guess.value === letter)
  )
);

Le MessageService définit une secretMessage calculée, la superSecretMessage encodée par le cipher que les joueurs travaillent à résoudre.

Le CipherService définit une unsolvedAlphabet calculée, une liste de toutes les lettres que le joueur n'a pas résolues, qui est dérivée de la liste de clés de chiffrement résolues dans decodedCipher.

Vérifier les modifications

Maintenant que superSecretMessage est un signal et que solvedMessage est un calcul, l'application devrait fonctionner. Testez les fonctionnalités du jeu:

  1. Glissez-déposez une LetterGuessComponent dans une LetterKeyComponent de votre CipherComponent pour essayer de résoudre le chiffrement et de décoder le message secret.
  2. Découvrez comment SecretMessageComponent se met à jour lorsque vous décoderez plus d'un message secret.
  3. Cliquez sur Personnaliser pour modifier l'expéditeur et le message, puis cliquez sur Créer et copier l'URL pour voir les valeurs à l'écran et la modification d'URL.
  4. Bonus: Copiez et collez l'URL dans un nouvel onglet ou partagez-la avec un ami. Vous verrez comment l'expéditeur et le message sont stockés dans l'URL.

GIF du jeu Cypher Angular, avec un message masqué décodé à l'écran qui indique "Les signaux Angular sont en version Preview développeur aujourd'hui dans la version 16".

6. Ajouter votre premier effet()

Il peut arriver que vous souhaitiez qu'un événement se produise. Avec effect(), vous pouvez planifier et exécuter une fonction de gestionnaire en réponse à des modifications de signaux.

Ajouter des confettis une fois le chiffrement terminé

Maintenant que l'application fonctionne, vous pouvez ajouter une touche amusante en ajoutant des confettis lorsque le chiffrement est résolu et que le message secret est décodé.

Pour ajouter des confettis, procédez comme suit sous le commentaire TODO(3): Add your first effect():

  1. Dans le fichier cipher.ts, planifiez un effet pour ajouter des confettis lorsque le message est décodé:

src/app/encryption/encryption.ts.

import * as confetti from 'canvas-confetti';

ngOnInit(): void {
  ...

  effect(() => {
    if (this.messages.superSecretMessage() === this.messages.solvedMessage()) {
      var confettiCanvas = document.getElementById('confetti-canvas');
      confetti.create()(confettiCanvas, { particleCount: 100 });
    }
  });
}

Notez que cet effet dépend d'un signal et d'une valeur calculée: this.messages.superSecretMessage() et this.messages.solvedMessage().

Effect vous permet de programmer la fonction confettis dans un contexte réactif pour suivre et réévaluer le moment où ses dépendances sont mises à jour.

Vérifier les modifications

  • Essayez de résoudre le problème de chiffrement (indice: vous pouvez remplacer le message par un texte plus court pour accélérer le test). Un confetti pop félicite votre premier effect() !

GIF du jeu Angular Cypher avec un message caché décodé à l'écran pour écrire "Confetti time!" et des confettis s'affichent une fois le message résolu.

7. Félicitations !

Votre algorithme de chiffrement angulaire est maintenant prêt à décoder et à partager des messages secrets ! Vous avez un message pour l'équipe Angular ? Taguez nos réseaux sociaux avec @Angular pour pouvoir les décoder. 🎉

Le jeu Angular Cypher est résolu en affichant le message "Angular Signals are in developer Preview in v16 today!" (Les signaux Angular sont en version Preview développeur aujourd'hui dans la version 16).

Vous avez maintenant trois nouvelles primitives réactives dans votre boîte à outils Angular pour simplifier votre développement et créer des applications plus rapides par défaut.

En savoir plus

Découvrez ces ateliers de programmation :

Consultez les ressources suivantes :