Apariencia
🖱️ Clase 5 — Eventos en Angular
📅 2026-07-18 · 🗂️ Proyecto:
AppClase04(destino en este repo:app-semana04) · 🎯 Event Binding y categorías de eventos⬅️ Viene después de Clase 4 (mismo día de clase, tema distinto: ahí es el ciclo de vida del componente, aquí son los eventos del DOM).
El profe compartió teoría sobre las categorías de eventos en Angular, y se practicó Event Binding capturando datos reales de un
<input>.
🗂️ Temas de esta clase
- Teoría del profe: las 3 categorías de eventos en Angular (DOM, personalizados, ciclo de vida).
- Ejercicio
envio: Event Binding con(click). - Ejercicio
informacion: capturar el valor de un<input>con(input)y$event.
📚 Teoría: categorías de eventos en Angular
Resumen de lo que compartió el profe (ya está también en
00-Notas/02-Conceptos.md, sección Categorías de eventos en Angular, para no duplicar el contenido).
Todo Event Binding usa la misma sintaxis, (evento)="metodo()", pero los eventos se agrupan en 3 categorías según de dónde vienen:
| Categoría | De dónde viene | Ejemplo |
|---|---|---|
| Eventos del DOM (nativos) | El navegador (clics, teclado, formularios) | (click), (input), (keyup.enter) |
| Eventos personalizados | Otro componente (comunicación hijo → padre) | @Output() cambio = new EventEmitter() |
| Eventos del ciclo de vida | El propio Angular | ngOnInit(), ngOnChanges(), ngOnDestroy() → ver ciclo-de-vida.md |
Dentro de Eventos del DOM, los más comunes:
| Grupo | Eventos | Ejemplo |
|---|---|---|
| Ratón | (click), (dblclick), (mouseenter), (mouseleave), (mousemove) | <button (click)="saltar()"> |
| Teclado | (keydown), (keyup), (keypress) — se pueden filtrar por tecla | (keyup.enter)="guardar()" |
| Formularios/Inputs | (input), (change), (blur), (focus) — el envío usa (ngSubmit) | (ngSubmit)="procesarFormulario()" |
📌 Faltan por ver con detalle: Eventos personalizados (
@Output()/EventEmitter) y el detalle completo de los del ciclo de vida (ya cubiertos enciclo-de-vida.md).
🏋️ Ejercicio: envio (Event Binding con (click))
📝 Este componente lo armé por mi cuenta como práctica, aparte de lo que mostró el profe con
saludo/bienvenida.
ts
import { Component } from '@angular/core';
@Component({
selector: 'app-envio',
imports: [],
templateUrl: './envio.html',
styleUrl: './envio.css',
})
export class Envio {
saludo = '';
saludar() {
this.saludo = '¡Hola! Gracias por escribir.';
}
}html
<button (click)="saludar()"> Enviar</button>
<p>{{ saludo }}</p>(click)="saludar()"— Event Binding: al hacer clic en el botón, se llama al métodosaludar()de la clase.saludar()le pone un valor asaludo(que arranca vacío''), y comosaludose muestra con interpolación ({{ saludo }}), el texto aparece en pantalla recién después del clic — no antes.
⚠️ Errores que salieron armando esto:
<p>{[saludo]}</p>— mezcla mal dos sintaxis (interpolación{{ }}y property binding[ ]). Angular no reconoce{[ ]}, y tiraNG5002: Unexpected character "EOF"(el parser del template se pierde). Se corrige usando doble llave:{{ saludo }}.- Al principio ni
saludonisaludar()existían en la claseEnvio(estaba vacía,export class Envio {}) — el HTML ya los usaba, pero la clase no los tenía definidos todavía.
🏋️ Ejercicio: informacion (capturar el valor de un <input> con $event)
Segundo ejemplo del profe, con el evento nativo (input) — captura lo que el usuario va escribiendo, tecla por tecla, usando el objeto $event del DOM:
ts
import { Component } from '@angular/core';
@Component({
selector: 'app-informacion',
imports: [],
templateUrl: './informacion.html',
styleUrl: './informacion.css',
})
export class Informacion {
texto = '';
escribir(evento: Event): void {
const input = evento.target as HTMLInputElement;
this.texto = input.value;
}
}html
<input (input)="escribir($event)" placeholder="Escribe tu apellido" />
<p>Escribiste : {{ texto }}</p>(input)="escribir($event)"— se dispara en cada tecla que se escribe (a diferencia de(change), que solo dispara cuando el input pierde el foco).$eventes el objeto nativo del evento del DOM; se lo pasamos entero al método.evento.target as HTMLInputElement—evento.targetes de tipo genérico (EventTarget), así que TypeScript no sabe que tiene.value. Elas HTMLInputElementes un cast: le dice a TypeScript "confía en mí, esto es un input", para poder leer.value.
⚠️ Errores que salieron armando esto: la clase
Informacionestaba vacía (export class Informacion {}) y el HTML ya llamaba aescribi($event)(con typo, sin la "r" final) — dabaProperty 'escribi' does not exist on type 'Informacion'. Se corrigió el nombre del método y se agregótexto/escribir()a la clase.
▶️ Cómo correrlo
Mismo proyecto que ciclo-de-vida.md, ya armado en este repo:
$ cd 02-Ejercicios/app-semana04
$ npm install // solo la primera vez
$ npm start // = ng serve → http://localhost:4200/envio e informacion ya están cableados en app.html junto con saludo/bienvenida.
🏋️ Ejercicios con solución
Ejercicio 1 — Contador de clics
Armar un componente con un botón y un contador que empieza en 0. Cada clic en el botón debe sumar 1 al contador y mostrarlo en pantalla con interpolación. Mismo patrón que envio, pero en vez de poner un texto fijo, hay que incrementar un número.
Ver solución
ts
import { Component } from '@angular/core';
@Component({
selector: 'app-contador',
imports: [],
templateUrl: './contador.html',
styleUrl: './contador.css',
})
export class Contador {
clics = 0;
contar() {
this.clics++;
}
}html
<button (click)="contar()">Clic aquí</button>
<p>Clics: {{ clics }}</p>Ejercicio 2 — Capturar el valor de un <select> con (change)
Armar un componente con un <select> de 2-3 opciones (por ejemplo, colores o ciudades). Cada vez que el usuario cambia la opción elegida, se debe guardar el valor seleccionado y mostrarlo con interpolación. Mismo patrón que informacion (usar $event, leer .value y castear), pero con el evento (change) en vez de (input), y sobre un <select> en vez de un <input>.
Ver solución
ts
import { Component } from '@angular/core';
@Component({
selector: 'app-color-favorito',
imports: [],
templateUrl: './color-favorito.html',
styleUrl: './color-favorito.css',
})
export class ColorFavorito {
color = '';
seleccionar(evento: Event): void {
const select = evento.target as HTMLSelectElement;
this.color = select.value;
}
}html
<select (change)="seleccionar($event)">
<option value="rojo">Rojo</option>
<option value="verde">Verde</option>
<option value="azul">Azul</option>
</select>
<p>Color elegido: {{ color }}</p>💡 El cast cambia de
HTMLInputElementaHTMLSelectElementporqueevento.targetahora es el<select>, no un<input>— mismo truco, distinto tipo de elemento del DOM.
❓ Preguntas y respuestas
1. ¿Diferencia entre (input) y (change)?
(input)se dispara en cada tecla que se escribe (o cada cambio inmediato, como mover un slider).(change)se dispara una sola vez, cuando el elemento pierde el foco (o, en un<select>, al confirmar la opción elegida).
2. ¿Para qué sirve $event y por qué a veces hace falta un cast como as HTMLInputElement?
$eventes el objeto nativo del evento del DOM (el mismo que llega en JS puro); se lo pasamos al método para poder leer datos como el valor escrito. Su tipo genérico esEvent, yevento.targetes de tipoEventTarget— muy genérico, sin propiedad.value. El cast (as HTMLInputElement,as HTMLSelectElement, etc.) le dice a TypeScript el tipo real del elemento para poder acceder a.valuesin error de compilación.
3. Según la tabla de categorías de eventos de esta clase, ¿en qué categoría cae (click) y en cuál @Output()?
(click)es un evento del DOM (nativo) — viene del navegador.@Output()conEventEmitteres un evento personalizado — lo define el propio componente para comunicarse de hijo a padre. Son categorías distintas aunque ambas usen la misma sintaxis(evento)="metodo()"en el binding.
📎 Apuntes relacionados
ciclo-de-vida.md— primera parte de esta clase (hooks del ciclo de vida).02-Conceptos.md(sección Data Binding → Categorías de eventos en Angular) — la teoría completa, con más detalle del objeto$event.
➡️ Siguiente
Ver Eventos personalizados (@Output()/EventEmitter, comunicación hijo → padre), que quedó pendiente de la teoría del profe.