Sergio Hidalgo
Apasionado por la tecnología. Ninja Developer, FullStack, Adm Servidores, Profesor de Angular, Node, Phaser, Javascript. sergiohidalgocaceres@gmail.com https://www.facebook.com/groups/607163139705114/
Dividir en componentes
app-root
app-formulario
app-listado
Diagrama de elementos
Generemos dos componentes: formulario y listado.
Agregarlos a app.component
<!-- app.component.html -->
<app-formulario></app-formulario>
<app-listado></app-listado>app-root
app-formulario
app-listado
Diagrama de elementos
app-tarea
Generemos un tercer componente: tarea
Agregarlo a listado.component
<!-- listado.component.html -->
<app-tarea></app-tarea>app-root
app-formulario
app-listado
El flujo de información ahora va desde "formulario" hacia el app.component y éste a su vez envía la información a "listado" y "listado" la envía a "tarea"
app-tarea
app-root
app-formulario
app-listado
Cuando "formulario" agrega una tarea, emite la señal "onNuevaTarea"
app-tarea
(onNuevaTarea)
app-root
app-formulario
app-listado
"app" envía la nueva tarea a través de la propiedad "tareas" del componente "listado"
app-tarea
(onNuevaTarea)
[tareas]
app-root
app-formulario
app-listado
"listado" envía la tarea al componente "tarea"
app-tarea
(onNuevaTarea)
[tareas]
[tarea]
El evento o señal "onNuevaTarea" ejecuta el método "grabar" al cual le pasa como parámetro la tarea creada.
<!-- app.component.html -->
<app-formulario (onNuevaTarea)="grabar($event)"></app-formulario>
<app-listado [tareas]="tareas"></app-listado>@Input
El decorador Input permite crear nuestras propias entradas.
import { Input } from "@angular/core"El Input debe importarse de la librería "@angular/core"
@Input() tareas: ITarea[]Podemos usar el Input especificando un nombre. Este nombre se convierte en una propiedad.
Es decir, podemos llamar a esta propiedad usando el objeto "this".
this.tareasPodemos usarla para interpolar o en *ngFor, *ngIf, etc.
<div *ngFor="let tarea of tareas">
{{tarea.titulo}}
</div><!-- app.component.html -->
<app-listado [tareas]="tareas"></app-listado>Los Inputs se pueden manejar con alias
<!-- listado.component.ts -->
...
@Input("tareas") listaTareas: ITarea[]
...En este caso "tareas" es el alias del Input.
El Input es asignado a la propiedad "listaTareas".
@Output
El decorador Output permite crear nuestras propias salidas (eventos, señales)
import { Output } from "@angular/core"El Output debe importarse de la librería "@angular/core"
@Ouput() onNuevaTarea = new EventEmitter<ITarea>()Podemos usar el Output especificando un nombre. Este nombre se convierte en una propiedad de tipo "EventEmitter".
Es decir, podemos llamar a esta propiedad usando el objeto "this".
this.onNuevaTareaLa clase "EventEmitter" tiene varios métodos. Uno de ellos se llama "emit"
this.onNuevaTarea.emit(tarea)<!-- app.component.html -->
<app-formulario (onNuevaTarea)="grabar($event)"></app-formulario>Los Outputs se pueden manejar con alias
<!-- formulario.component.ts -->
...
@Output("onNuevaTarea") agregarTarea = new EventEmitter<ITarea>()
...En este caso "onNuevaTarea" es el alias del Output.
El Output es asignado a la propiedad "agregarTarea".
Tarea 1
Agregar un botón "Eliminar" a cada tarea.
Usar los métodos de arreglos "indexOf" para ubicar el índice de un elemento, y "splite" para eliminar uno o más elementos.
Encapsulation
La encapsulación tiene que ver con el ámbito o alcance de las reglas de CSS
@Component({
selector: ...
templateUrl: ...
styleUrls: ...
encapsulation: ...
})Encapsulation es una propiedad del JSON que define un componente a través del decorador @Component
import { ViewEncapsulation } from "@angular/core"Para utilizar "Encapsulation" necesitamos importar el template "ViewEncapsulation" desde "@angular/core"
ViewEncapsulation.Emulated
ViewEncapsulation.Native
ViewEncapsulation.None"Encapsulation" tiene tres posibles valores.
ViewEncapsulation.Emulated
<!-- formulario.component.html -->
<p>Formulario para agregar</p>Agreguemos un título al componente "formulario" usando una <p>.
<!-- listado.component.html -->
<p>Fecha: {{tarea.fecha}}</p>
<p>Solicitante: {{tarea.solicitante}}</p>
<p>Estado: {{tarea.estado}}</p>Agreguemos <p> al componente "listado".
<!-- listado.component.css -->
p {
font-style: italic
}Agreguemos una regla de estilos para las <p>
El cambio se refleja únicamente en el componente "listado"
¿Por qué?
En el inspector de elementos encontramos la respuesta.
Angular le agregó automáticamente el atributo "_ngcontent-c2".
Por defecto, Angular utiliza "ViewEncapsulation.Emulated" así no definamos la propiedad "encapsulation".
ViewEncapsulation.Native
Native y Emulated dan resultados iguales.
La diferencia está en la técnica usada.
Native usa "shadow-root", que es parecido a usar un iframe
"shadow-root" no es soportado por todos los navegadores aún.
ViewEncapsulation.None
Usar None significa que cualquier estilo definido fuera del componente puede afectar a las etiquetas html definidas dentro.
Referencias Locales
Las referencias locales son las que he llamado antes variables de controles
<!-- formulario.component.html -->
...
<input type="text" id="titulo" placeholder="Ingrese el título" #titulo>
<input type="date" id="fecha" placeholder="Ingrese la fecha" #fecha>
<input type="text" id="solicitante" placeholder="Ingrese el solicitante" #solicitante>
<select style="display: block" #estado>
<option value="" disabled selected>Elija un estado</option>
<option value="sin-asignar">Sin asignar</option>
<option value="asignada">Asignada</option>
<option value="en-proceso">En proceso</option>
<option value="terminada">Terminada</option>
<option value="cancelada">Cancelada</option>
</select>
...Reemplacemos el "ngModel" y "name" por referencias locales.
<!-- formulario.component.html -->
...
<button
class="btn waves-effect waves-light"
(click)="grabar(titulo, fecha, solicitante, estado)">
Grabar
</button>
...El botón "Grabar" ejecutará el método "grabar" pero tendrá como parámetros a las referencias locales.
<!-- formulario.component.ts-->
import * as moment from "moment";
...
grabar(titulo, fecha, solicitante, estado) {
this.modelo.titulo = titulo.value
this.modelo.fecha = moment(fecha.value).toDate()
this.modelo.solicitante = solicitante.value
this.modelo.estado = estado.value
this.onNuevaTarea.emit(this.modelo)
}
...El botón "Grabar" ejecutará el método "grabar" pero tendrá como parámetros a las referencias locales.
@ViewChild
@ViewChild es un decorador que nos permite acceder a elementos HTML
Mantengamos en mente a las referencias locales.
<!-- formulario.component.html -->
...
<input type="text" id="titulo" placeholder="Ingrese el título" #titulo>
<input type="date" id="fecha" placeholder="Ingrese la fecha" #fecha>
<input type="text" id="solicitante" placeholder="Ingrese el solicitante" #solicitante>
<select style="display: block" #estado>
<option value="" disabled selected>Elija un estado</option>
<option value="sin-asignar">Sin asignar</option>
<option value="asignada">Asignada</option>
<option value="en-proceso">En proceso</option>
<option value="terminada">Terminada</option>
<option value="cancelada">Cancelada</option>
</select>
...Podemos acceder a ellas desde el typescript usando el ViewChild
<!-- formulario.component.ts -->
import { ViewChild } from "@angular/core"
...
@ViewChild("titulo") tituloTarea
@ViewChild("fecha") fechaTarea
@ViewChild("solicitante") solicitanteTarea
@ViewChild("estado") estadoTarea
...<!-- formulario.component.ts -->
grabar() {
console.log(this.tituloTarea)
}Modificamos el método "grabar" para analizar el ViewChild
Observamos que lo devuelto es un "ElementRef"
Modifiquemos el typescript para reflejar el tipo de dato correcto
<!-- formulario.component.ts -->
import { ViewChild, ElementRef } from "@angular/core"
...
@ViewChild("titulo") tituloTarea: ElementRef
@ViewChild("fecha") fechaTarea: ElementRef
@ViewChild("solicitante") solicitanteTarea: ElementRef
@ViewChild("estado") estadoTarea: ElementRef
...// devuelve el valor del input
this.titulo.nativeElement.value
// nos permite modificar los estilos de la etiqueta
this.titulo.nativeElement.style
this.titulo.nativeElement.style.backgroundColor = "red""ElementRef" contiene una propiedad "nativeElement" que nos da acceso a modificar las características y valores de la etiqueta HTML.
Tarea 2
1. Crear tres componentes: "GeneradorNumero", "Par", "Impar"
2. El componente "GenerarNumero" contendrá dos botones: "Iniciar" y "Detener".
3. El botón "Iniciar" hará que el componente "GenerarNumero" emita un número incremental desde 1 cada segundo (setInterval).
4. El botón "Detener" hará que el componente deje de emitir (clearInterval)
5. Los componentes "Par" e "Impar" se repetirán tantas veces se hayan emitido números pares e impares respectivamente.
6. Los componentes "Par" e "Impar" deben mostrar el número que los generó.
By Sergio Hidalgo
División en componentes, Entradas y Salidas, Alcance de CSS, Referencias Locales, Acceso a elementos HTML
Apasionado por la tecnología. Ninja Developer, FullStack, Adm Servidores, Profesor de Angular, Node, Phaser, Javascript. sergiohidalgocaceres@gmail.com https://www.facebook.com/groups/607163139705114/