1. Avant de commencer
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()
eteffect()
. - 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.
Prérequis
- Connaissances d'Angular et de Typescript
- Recommandation: regardez Repenser la réactivité avec les signaux pour en savoir plus sur la bibliothèque Angular Signals.
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é:
- 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.
- 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:
- Ouvrez un nouvel onglet du navigateur et accédez à https://github.com/linear/codelabs/tree/signals-get-started.
- Dupliquez et clonez le dépôt, puis utilisez la commande
cd codelabs/
pour y accéder. - Vérifiez la branche de code de démarrage avec la commande
git checkout signals-get-started
. - Ouvrez le code dans VSCode ou dans l'IDE de votre choix.
- Pour installer les dépendances requises pour l'exécution du serveur, exécutez la commande
npm install
. - Pour exécuter le serveur, utilisez la commande
ng serve
. - 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.
Pour commencer, parcourez la version finale de ce que vous allez développer: Angular Signals Cypher.
- Affichez le message codé à l'écran.
- 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.
- Si l'opération réussit, vous verrez comment le message sera mis à jour pour décoder davantage le message secret.
- 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.
- 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.
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:
- Dans le fichier
service.message.ts
, utilisez la bibliothèque de signaux pour rendresuperSecretMessage
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.
- Dans les fichiers
secret-message.ts
etservice.message.ts
, remplacez toutes les références desuperSecretMessage
parsuperSecretMessage()
:
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 votresuperSecretMessage
est configuré.
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:
- Dans le fichier
service.message.ts
, utilisez la bibliothèque de signaux pour rendresolvedMessage
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()
.
- Dans le fichier
secret-message.ts
, remplacez toutes les références desolvedMessage
parsolvedMessage()
:
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:
- Glissez-déposez une
LetterGuessComponent
dans uneLetterKeyComponent
de votreCipherComponent
pour essayer de résoudre le chiffrement et de décoder le message secret. - Découvrez comment
SecretMessageComponent
se met à jour lorsque vous décoderez plus d'un message secret. - 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.
- 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.
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()
:
- 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()
!
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. 🎉
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 :
- Premiers pas avec les composants autonomes
- Building a web application with Angular and Firebase (Créer une application Web avec Angular et Firebase)
Consultez les ressources suivantes :
- Angular.io
- Rethinking Reactivity with Signals (Repenser la réactivité avec les signaux) (Google I/O 2023)
- Nouveautés d'Angular (Google I/O 2023)