Data Binding Angular
Data Binding en Angular
Data Binding en Angular se define como la sincronización de los datos entre el componente y la vista y es una de sus características más populares.
PROPERTY BINDING
Property Binding es un mecanismo que consiste en la transferencia desde el componente hacia la vista, es decir, desde el componente se están pasando datos que configuran un elemento de la vista. Este enlace de propiedades permite definir propiedades a un elemento HTML, a un componente o a una directiva mediante expresiones y se pueden manejar estos valores y cambiarlos en caso de ser necesario.
Nota: Preciso recordar que no es lo mismo atributos que propiedades, mejor explicado en //www.pensemosweb.com/enlazado-propiedades-property-binding-angular/
En el ejemplo siguiente se puede observar como el atributo disabled envuelto entre corchetes tiene asignado el objeto boton y su propiedad test, definidas en el archivo typescript del componente. El uso de setTimeout permite cambiar la propiedad y realizar la sincronización automática de la vista.
component.ts
export class NuevoComponent implements OnInit {
boton={
test: true
};
constructor() { }
ngOnInit() {
setTimeout(() => {
this.boton.test=false;
},3000);
}
}
component.html
<button mat-button disabled = "true">Botón Normal</button>
<button mat-button [disabled] = "!boton.test">Botón Property</button>
Las directivas son atributos asignables a un componente y que permiten manejar el DOM y añadir propiedades a elementos HTML en la vista del componente.
DIRECTIVAS *ngIf & *ngFor
Las directivas *ngIf & *ngFor se denominan directivas estructurales, ya que, permiten manipular la estructura del DOM. Estas directivas son atributos que se añaden a un elemento HTML y que nos permiten generar un condicional y un bucle respectivamente. La directiva *ngIf permite ocultar el elemento o mostrarlo según la condición y la directiva *ngFor permite generar un bucle que repite el elemento el número de veces que se cumpla.
*ngIf
<div>
<img *ngIf="usuario.imaprofile" [src]="usuario.imaprofile">
<span>{{ usuario.nombre }}</span>
<span>{{ usuario.pais}}</span>
</div>
<div>
<img *ngIf="usuario.imaprofile" [src]="usuario.imaprofile">
<img *ngIf="!usuario.imaprofile" [src]="profiledefault">
<span>{{ usuario.nombre }}</span>
<span>{{ usuario.pais}}</span>
</div>
*ngif (if - else)
<div *ngIf=usuario;then datosValidos; else sinDatos>
</div>
<ng-template #datosValidos>
<span>{{ usuario.nombre }}</span>
<span>{{ usuarios.pais }}</span>
</ng-template>
<ng-template #sinDatos>
<span>No existe usuario</span>
</ng-template>
*ngFor
<div *ngFor="let usuario of arrayUsuarios">
<img *ngIf="usuario.imaprofile" [src]="usuario.imaprofile">
<img *ngIf="!usuario.imaprofile" [src]="DEFAULT_PICTURE">
<span>{{ usuario.nombre }}</span>
<span>{{ usuario.pais }}</span>
</div>
*ngSwitch
<ul [ngSwitch]="color">
<li *ngSwitchCase=" 'yellow' ">
El color es el amarillo
</li>
<li *ngSwitchCase="'red'">
El color es el rojo
</li>
</ul>
DIRECTIVAS DE ATRIBUTO
ngClass
Permite asignar una clase a un elemento con la opción de añadirla si se cumple una condición.
<span [class.oferta] = "coche.precio <= 1000">{{coche.precio}}€ </span>
<span [ngClass] = '{ "oferta" : coche.precio <=1000 }'>{{ coche.precio }} </span>
EVENT BINDING
El Event Binding es la transferencia que usa Angular para manejar los eventos, esta transferencia va desde la vista hacia el componente. De la misma forma que Javascript, se añade un atributo al elemento HTML y se le asigna una función con sus parámetros (si los hay). Pero en Angular este atributo va cerrado entre paréntesis y para lanzar un evento, Angular dispone de la palabra reservada $event que lanza un evento de tipo Angular y desde el archivo typescript del componente podrá ser capturado.
<button (click) = "onClick($event)">
Botón
</button>
<input (keyup) = "onKeyUp($event)">
export class BotonComponent implements OnInit {
constructor() { }
ngOnInit() {
}
onClick($event){
console.log("Event Click",$event);
}
onKeyUp($event){
console.log("Event Tecla presionada",$event);
}
}
DIRECTIVAS PERSONALIZADAS
Crear directiva
ng generate directive fondo
Ejemplo de directiva personalizada
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[edFondo]'
})
export class FondoDirective {
constructor(public elemento: ElementRef) {
}
ngOnInit(){
var fondo = this.elemento.nativeElement;
fondo.style.color= "white";
fondo.style.background = "orange";
console.log(fondo.innerText);
}
}
<div class="container">
<p edFondo>hola que tal</p>
</div>
COMUNICACIÓN ENTRE COMPONENTES
INPUT DINÁMICO (@INPUT)
Este decorador permite que la propiedad de un componente padre esté disponible en un componente hijo mediante el uso de atributos.
En el código de ejemplo siguiente se ha creado una lista de usuarios del tipo Usuario en el componente padre.
import { Component, OnInit } from '@angular/core';
import { Usuario } from "../../shared/model/usuario";
@Component({
selector: 'pre-lista-padre',
templateUrl: './lista-padre.component.html',
styleUrls: ['./lista-padre.component.css']
})
export class ListaPadreComponent implements OnInit {
usuario1: Usuario;
usuario2: Usuario;
usuario3: Usuario;
listaUsuarios : Usuario[];
constructor() { }
ngOnInit() {
this.usuario1 = {
id:1,
nombre: "Mónica Cañero",
pais: "Bolivia",
};
this.usuario2 = {
id:2,
nombre: "Susana Beltrán",
pais: "España"
};
this.usuario3 = {
id:3,
nombre: "Vanesa Pantoja",
pais: "Venezuela"
};
this.listaUsuarios = [ this.usuario1,this.usuario2,this.usuario3 ];
}
}
En la plantilla del componente padre añadimos el selector del componente hijo y la directiva de atributo asignando los datos.
<div>
<pre-lista-hijo *ngFor="let user of listaUsuarios" [usuario] = "user"></pre-lista-hijo>
</div>
En el componente hijo importamos el modelo de Usuario y se añade el decorador @Input() y a continuación el atributo usuario de tipo Usuario. Este decorador es el que permite que desde la plantilla o vista del componente hijo sea posible el acceso a los datos (usuario).
import { Component, OnInit, Input } from '@angular/core';
import { Usuario } from "../../../shared/model/usuario";
@Component({
selector: 'pre-lista-hijo',
templateUrl: './lista-hijo.component.html',
styleUrls: ['./lista-hijo.component.css']
})
export class ListaHijoComponent implements OnInit {
@Input()
usuario: Usuario;
constructor() { }
ngOnInit() {
}
}
En la vista del componente hijo ya es posible mostrar los valores obteniéndolos del componente padre.
<div>
<span>{{ usuario.nombre }}</span>
<span>{{ usuario.pais }}</span>
</div>
OUTPUT DINÁMICO (@OUTPUT)
Este decorador junto con EventEmitter permite que un evento de un componente hijo esté disponible en un componente padre.
Manteniendo el código del ejemplo anterior la plantilla del componente hijo solo es necesario añadir un evento Angular y asignarle la función que emitirá los datos.
<div (click) = "capturarEvento(usuario)">
<span>{{ usuario.nombre }}</span>
<span>{{ usuario.pais }}</span>
</div>
Tipos de evento más comunes en Angular
Desde el componente hijo es necesario importar el Output y el EventMitter, para poder añadir el decorador @Output y a continuación crear un objeto EventEmitter. Al final de la clase se crea el método (que es el asignado anteriormente en la plantilla), incluyendo el tipo de objeto como parámetro. Este método llama al método emit() de la clase EventMitter que es el que propaga los datos.
import { Component, OnInit, Input,Output, EventEmitter } from '@angular/core';
import { Usuario } from "../../../shared/model/usuario";
@Component({
selector: 'pre-lista-hijo',
templateUrl: './lista-hijo.component.html',
styleUrls: ['./lista-hijo.component.css']
})
export class ListaHijoComponent implements OnInit {
@Input()
usuario: Usuario;
@Output()
propagarDatos = new EventEmitter<Usuario>();
constructor() { }
ngOnInit() {
}
capturarEvento(ev: Usuario){
this.propagarDatos.emit(ev);
}
}
Desde la vista del componente padre se añade como atributo el objeto anteriormente creado (propagarDatos) cerrado entre paréntesis y se le asigna una función (mostrarDato)pasando como parámetros el "$event" que es una palabra reservada de Angular.
<div>
<pre-lista-hijo *ngFor="let user of listaUsuarios" [usuario] = "user" (propagarDatos)="mostrarDatos($event)"></pre-lista-hijo>
</div>
Al final de la clase se crea el método que será el que maneje los datos a través del parámetro $event.
import { Component, OnInit } from '@angular/core';
import { Usuario } from "../../shared/model/usuario";
@Component({
selector: 'pre-lista-padre',
templateUrl: './lista-padre.component.html',
styleUrls: ['./lista-padre.component.css']
})
export class ListaPadreComponent implements OnInit {
usuario1: Usuario;
usuario2: Usuario;
usuario3: Usuario;
listaUsuarios : Usuario[];
constructor() { }
ngOnInit() {
this.usuario1 = {
id:1,
nombre: "Mónica Cañero",
pais: "Bolivia",
};
this.usuario2 = {
id:2,
nombre: "Susana Beltrán",
pais: "España"
};
this.usuario3 = {
id:3,
nombre: "Vanesa Pantoja",
pais: "Venezuela"
};
this.listaUsuarios = [ this.usuario1,this.usuario2,this.usuario3 ];
}
mostrarDatos($event){
console.log("Nombre del registro pulsado: ",$event.nombre);
}
}
PIPES O FILTROS
Los pipes son funciones de Angular que permiten modificar datos (que a menudo son rutinarios o repetitivos) en la vista, como pueden ser formatear la fecha, modificar el texto...
export class ExternoComponent implements OnInit {
public fecha: Date;
ngOnInit()
{
this.fecha=new Date();
}
<hr>
<p>{{ fecha | date: "dd/MM/y"}}</p>
<hr>
<hr>
<p>{{ fecha | date: "fullDate"}}</p><br>
<p>{{ "texto en mayúsculas con PIPES" | uppercase }}</p>
<hr>
PIPES PERSONALIZADOS
module.ts
import { CalculadoraPipe } from "./pipes/calculadora.pipe";
declarations:[ CalculadoraPipe ]
component.ts
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({
name: "calculadora"
})
export class CalculadoraPipe implements PipeTransform{
//dato | calculadora: dato2
//param1 param2
transform(value1:any,value2:any){
let operaciones =`
Suma: ${value1+value2} -
Resta: ${value1-value2} -
Multiplicación: ${value1*value2} -
División: ${value1/value2}
`;
return operaciones;
}
}
component.html
<div>
<p>{{ 4 | calculadora: 2 }}</p>
</div>
Para poder comentar es necesario iniciar sesión