1. Antes de comenzar
Los indicadores de Angular presentan tres primitivas reactivas al Angular que conoces y amas, lo que simplifica tu desarrollo y te ayuda a compilar apps más rápidas de forma predeterminada.
Qué compilarás
- Aprenderás sobre las tres primitivas reactivas que se introdujeron con los indicadores de Angular:
signal()
,computed()
yeffect()
. - Usa los indicadores de Angular para potenciar un juego de cifrado de Angular. Los algoritmos de cifrado son sistemas para encriptar y desencriptar datos. En este juego, los usuarios pueden decodificar un mensaje secreto arrastrando y soltando pistas para resolver un algoritmo de cifrado, personalizar el mensaje y compartir la URL a fin de enviar mensajes secretos a los amigos.
Requisitos previos
- Conocimientos de Angular y TypeScript
- Recomendado: Mira el video Rethinking Reactivity with Signals para obtener más información sobre la biblioteca de Angular Signals
2. Obtén el código
Todo lo que necesitas para este proyecto está en Stackblitz. Stackblitz es el método recomendado para trabajar en este codelab. Como alternativa, clona el código y ábrelo en tu entorno de desarrollo favorito.
Abre Stackblitz y ejecuta la app.
Para comenzar, abre el vínculo de Stackblitz en tu navegador web favorito:
- Abra una nueva pestaña del navegador y vaya a https://stackblitz.com/edit/io-signals-codelab-starter?file=src%2Fcrypt%2Fservice.crypt.ts,src%2Fsecret-message%2Fservice.message.ts&service.massage.ts
- Bifurca Stackblitz para crear tu propio lugar de trabajo editable. Stackblitz debería ejecutar automáticamente la app, y ¡listo!
Alternativa: Clona el repositorio y entrega la app
El uso de VSCode o un IDE local es un método alternativo para trabajar en este codelab:
- Abre una nueva pestaña del navegador y ve a https://github.com/angular/codelabs/tree/signals-get-started.
- Bifurca y clona el repositorio, y usa el comando
cd codelabs/
para moverte al repositorio. - Revisa la rama de código de inicio con el comando
git checkout signals-get-started
. - Abre el código en VSCode o en el IDE que prefieras.
- A fin de instalar las dependencias necesarias para ejecutar el servidor, usa el comando
npm install
. - Para ejecutar el servidor, usa el comando
ng serve
. - Abre una pestaña del navegador en http://localhost:4200.
3. Cómo establecer un modelo de referencia
El punto de partida es un juego de cifrado de Angular, pero aún no funciona. Los indicadores de Angular potenciarán la funcionalidad del juego.
Para comenzar, repasa la versión terminada de lo que compilarás: Cypher de los indicadores de Angular.
- Visualiza el mensaje codificado en la pantalla.
- Arrastra y suelta un botón de letra en el teclado para resolver el cifrado y decodificar el mensaje secreto.
- Si se realiza de forma correcta, observa cómo se actualiza el mensaje para decodificar más mensajes secretos.
- Haz clic en Personalizar para cambiar el Remitente y el Mensaje y, luego, en Crear y copiar URL para ver los valores en la pantalla y la URL cambia.
- Bonificación: Copia y pega la URL en una pestaña nueva o compártela con un amigo, y mira cómo se almacenan el remitente y el mensaje en la URL.
4. Define tu primer indicador()
Un indicador es un valor que puede indicarle a Angular cuándo cambia. Algunos indicadores se pueden cambiar directamente, mientras que otros calculan sus valores a partir de los valores de otros. En conjunto, los indicadores crean un grafo dirigido de dependencias que modela el flujo de datos en tu app.
Angular puede usar las notificaciones de los indicadores para saber qué componentes deben detectarse ante un cambio o ejecutar las funciones de efecto que usted defina.
Convierte superSecretMessage
en signal()
superSecretMessage
es un valor en MessageService
que define el mensaje secreto que decodifica el jugador. Actualmente, el valor no notifica a la app sobre los cambios, por lo que no funciona el botón Customize. Puedes resolverlo con una señal.
Si haces que superSecretMessage
sea un indicador, podrás notificar a las partes de la app que dependan de saber cuándo cambió el mensaje. Cuando personalices el mensaje en un diálogo, establecerás el indicador para actualizar el resto de la app con el mensaje nuevo.
Para definir tu primer indicador, sigue estos pasos en el comentario TODO(1): Define your first signal()
de cada archivo:
- En el archivo
service.message.ts
, usa la biblioteca de indicadores para hacer quesuperSecretMessage
sea reactivo:
src/app/secret-message/service.message.ts
superSecretMessage = signal(
'Angular Signals are in developer preview in v16 today!'
);
Se te pedirá automáticamente que importes signal
desde @angular/core
. Si actualizas la página, es probable que encuentres errores donde hace referencia a superSecretMessage
. Esto se debe a que cambiaste el tipo de superSecretMessage
de string
a SettableSignal<string>
. Para solucionar este problema, cambia todas las referencias de superSecretMessage
a fin de usar la API de Signals. Cuando leas el valor, llama al método get superSecretMessage()
. Y donde escribas el valor, usa la API de .set
en SettableSignal
para configurar el valor nuevo del mensaje.
- En los archivos
secret-message.ts
yservice.message.ts
, actualiza todas las referencias desuperSecretMessage
asuperSecretMessage()
:
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()
Explore los otros dos indicadores
- Observa que tienes otros dos indicadores en tu app:
src/app/crypt/service.crypt.ts.
cipher = signal(this.createNewCipherKey());
decodedCipher = signal<CipherKey[]>([]);
El CipherService
define una señal cipher
, una asignación generada de forma aleatoria de pares clave-valor de una letra del alfabeto a una nueva letra cipher
. Se usa para desordenar el mensaje y determinar si el jugador encuentra una coincidencia exitosa en el teclado.
También tienes una señal decodedCipher
de los pares clave-valor decodificados con éxito que agregarás a medida que el jugador resuelve el algoritmo de cifrado.
Un atributo potente y único del diseño de la biblioteca de indicadores de Angular es que puedes incorporar la reactividad en todas partes. Definiste indicadores una vez en los servicios de la app y puedes usarlos en una plantilla, componentes, canalizaciones, otros servicios o cualquier lugar donde puedas escribir código de aplicación. No están limitados al alcance del componente o no están vinculados a él.
Verifica los cambios
- Debes realizar un paso más para que la app funcione. Por ahora, intenta agregar un elemento
console.log()
en diferentes partes de tu app para ver cómo se configura tu nuevosuperSecretMessage
.
5. Define tu primer compute()
En muchas situaciones, puede que derive el estado de valores existentes. Es mejor tener la actualización del estado derivado cuando cambia el valor dependiente.
Con computed()
, puedes expresar de forma declarativa un indicador que derive su valor de otros indicadores.
Convierte solvedMessage
en computed()
solvedMessage
traduce el valor secretMessage
de codificado a decodificado con la señal decodedCipher
.
Esto es extraordinario porque puede ver que deriva un cálculo basado en otro, por lo que cada vez que cambia una señal dentro de ese contexto reactivo asignado, se notifican las dependencias.
Actualmente, solvedMessage
no se actualiza cuando cambias secretMessage
, decodedCipher
o superSecretMessage
. Por lo tanto, no ves actualizaciones en la pantalla cuando el reproductor resuelve el cifrado.
Si haces que solvedMessage
se calcule, crearás un contexto reactivo para que, cuando actualices el mensaje o resuelvas el algoritmo de cifrado, puedas obtener la actualización de estado de las dependencias con seguimiento.
Para convertir solvedMessage
en computed()
, sigue estos pasos en el comentario TODO(2): Define your first computed()
de cada archivo:
- En el archivo
service.message.ts
, usa la biblioteca de indicadores para hacer quesolvedMessage
sea reactivo:
src/app/secret-message/service.message.ts.
solvedMessage = computed(() =>
this.translateMessage(
this.secretMessage(),
this.cipher.decodedCipher()
)
);
Se te pedirá automáticamente que importes computed
desde @angular/core
. Si actualizas la página, es probable que encuentres errores donde hace referencia a solvedMessage
. Esto se debe a que cambiaste el tipo de superSecretMessage
de string
a Signal<string>
, una función. Para solucionar este problema, cambia todas las referencias de solvedMessage
a solvedMessage()
.
- En el archivo
secret-message.ts
, actualiza todas las referencias desolvedMessage
asolvedMessage()
:
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>
Ten en cuenta que, a diferencia de superSecretMessage
, solvedMessage
no es SettableSignal
, no puedes cambiar su valor directamente. En su lugar, su valor se mantiene actualizado cuando se actualiza cualquiera de sus indicadores de dependencia (secretMessage
y decodedCipher
).
Explora las otras dos funciones computed()
- Observa que tienes otros dos valores calculados en tu app:
src/app/secret-message/service.message.ts.
secretMessage = computed(() =>
this.translateMessage(
this.superSecretMessage(),
this.cipher.cipher()
)
);
src/app/crypt/service.crypt.ts.
unsolvedAlphabet = computed(() =>
ALPHABET.filter(
(letter) => !this.decodedCipher().find((guess) => guess.value === letter)
)
);
MessageService
define un secretMessage
calculado, el superSecretMessage
codificado por el cipher
que los jugadores deben resolver.
CipherService
define un unsolvedAlphabet
calculado, una lista de todas las letras que el jugador no resolvió, que deriva de la lista de claves de cifrado resueltas en decodedCipher
.
Verifica los cambios
Ahora que superSecretMessage
es un indicador y solvedMessage
es un cálculo, la app debería funcionar. Prueba las funciones del juego:
- Arrastra y suelta una
LetterGuessComponent
en unaLetterKeyComponent
en tuCipherComponent
para resolver el cifrado y decodificar el mensaje secreto. - Observa cómo se actualiza
SecretMessageComponent
a medida que decodificas más mensajes secretos. - Haz clic en Personalizar para cambiar el Remitente y el Mensaje y, luego, en Crear y copiar URL para ver los valores en la pantalla y la URL cambia.
- Bonificación: Copia y pega la URL en una pestaña nueva o compártela con un amigo, y mira cómo se almacenan el remitente y el mensaje en la URL.
6. Agrega tu primer efecto()
En algunas ocasiones, es posible que quiera que ocurra algo cuando un indicador tiene un valor nuevo. Con effect()
, puedes programar y ejecutar una función de controlador en respuesta a los cambios de indicadores.
Agrega confeti cuando se resuelve el algoritmo de cifrado
Ahora que la app es funcional, puedes agregar confeti cuando el código de cifrado se resuelva y el mensaje secreto se decodifique.
Para agregar confeti, sigue estos pasos en el comentario TODO(3): Add your first effect()
:
- En el archivo
cipher.ts
, programa un efecto para agregar confeti cuando se decodifique el mensaje:
src/app/crypt/crypt.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 });
}
});
}
Observa que este efecto depende de una señal y un valor calculado: this.messages.superSecretMessage()
y this.messages.solvedMessage()
.
Effect te ayuda a programar la función de confeti en un contexto reactivo para hacer un seguimiento y volver a evaluar cuando se actualizan sus dependencias.
Verifica los cambios
- Intenta resolver el algoritmo de cifrado (pista: puedes cambiar el mensaje a algo corto para probarlo más rápido). Un confeti pop te felicitará por tu primer
effect()
.
7. Felicitaciones
Tu algoritmo de cifrado de Angular ya está listo para decodificar y compartir mensajes secretos. ¿Tienes un mensaje para el equipo de Angular? Etiqueta nuestras redes sociales en @Angular para que podamos decodificarlo. 🎉
Ahora tienes tres primitivas reactivas nuevas en tu caja de herramientas de Angular para simplificar tu desarrollo y compilar apps más rápidas de forma predeterminada.
Más información
Consulta estos codelabs:
- Cómo comenzar a usar componentes independientes
- Building a web application with Angular and Firebase
Lee los siguientes materiales:
- Angular.io
- Reformulación de la reactividad con indicadores (Google I/O 2023)
- Novedades de Angular (Google I/O 2023)