Siguiendo con la Introducción a Angular 2, hoy voy a entrar en detalle con un par de conceptos que te sonarán de AngularJS:
Data Binding
Uno de los principales valores de Angular es que nos abstrae de la lógica pull/push asociada a insertar y actualizar valores en el HTML y convertir las respuestas de usuario (inputs, clicks, etc) en acciones concretas. Escribir toda esa lógica a mano (lo que típicamente se hacía con JQuery) es tedioso y propenso a errores, y Angular 2 lo resuelve por nosotros gracias al Data Binding.
Simplifiquemos el template anterior para centrarnos en el data binding:
<div>{{todo.subject}}</div>
<todo-detail [todo]="selectedTodo"></todo-detail>
<div (click)="selectTodo(todo)"></div>
Angular 2 dispone de 4 formas de data binding:
- Interpolación: (Hacia el DOM)
Al hacer{{todo.subject}}
, Angular se encarga de insertar el valor de esa propiedad del componente entre las etiquetas<div>
donde lo hemos definido. Es decir, evalúa todo.subject e introduce su resultado en el DOM. -
Property binding: (Hacia el DOM)
Al hacer[todo]="selectedTodo"
, Angular está pasando el objeto selectedTodo del Componente padre a la propiedad todo del Componente hijo, en este caso de TodoDetailComponent. Recordemos de la sección Componentes que para esto el componente TodoDetailComponent habrá definido una propiedad todo con el decorador @Input(). -
Event binding: (Desde el DOM)
Al hacer(click)="selectTodo(todo)"
, le indicamos a Angular que cuando se produzca un evento click sobre esa etiqueta<div>
, llame al método selectTodo del Componente, pasando como atributo el objeto todo presente en ese contexto. (Aunque hemos simplificado el ejemplo, esto venía de un bucle que itera el array todos obteniendo la variable todo).Angular mapea los eventos típicos de cualquier elemento del DOM para que los podamos utilizar como event binding.
En la sección Componentes hablábamos del decorador @Output(). Este sería otro ejemplo de event binding, creando un pseudoevento que se llame desde dentro del componente hijo y accione un método del componente padre.
-
Two-way binding: (Desde/Hacia el DOM)
Un caso importante que no hemos visto con los ejemplos anteriores es el binding bi-direccional, que combina event binding y property binding, como podemos ver en el siguiente ejemplo:<input [(ngModel)]="todo.subject">
En este caso, el valor de la propiedad fluye a la caja de input como en el caso property binding, pero los cambios del usuario también fluyen de vuelta al componente, actualizando el valor de dicha propiedad.
Angular procesa los data binding una vez por cada ciclo de eventos JavaScript, desde la raíz de la aplicación siguiendo el arbol de componentes en orden de profundidad.
Los siguientes gráficos de la documentación de Angular 2 ilustran la importancia del data-binding para la comunicación entre componentes, así como componente-template.
Directivas
Si conoces AngularJS, ya conoces el concepto de directiva. En caso contrario, lo que debes saber es que los templates de Angular son dinámicos: Cuando Angular los renderiza, transforma el DOM en base a las instrucciones de las directivas que encuentra.
En Angular 2, una directiva se define como una clase que utiliza el decorador @Directive.
Componentes Angular Nivel PRO
Cuando hemos hablado de los componentes y hemos dicho que eran similares a un controlador con una vista, muchos habréis pensando «más bien se parece a una directiva…». Es cierto, un Componente es un caso concreto de directiva que siempre va asociado a un template y al que por ser un elemento tan importante en Angular 2 se le ha dado un decorador propio.
Un Componente es una Directiva con template. De hecho @Component es un decorador @Directive extendido con características propias de los templates.
Hay otros dos tipos de directivas, las estructurales y las atributo, y normalmente las vemos en forma de etiquetas de elementos HTML como atributos. Además, igual que con su predecesor, podremos crear nuestra propias directivas.
Directivas estructurales
Estas directivas, que se diferencian fácilmente al ser precedidas por un asterisco, alteran el layout añadiendo, eliminando o reemplazando elementos en el DOM.
Las directivas estructurales comienzan por asterisco y sirven para alterar el DOM.
Veamos un par de ejemplos de directivas estructurales:
- *ngIf: si la condición se cumple, su elemento se inserta en el DOM, en caso contrario, se elimina del DOM. (equivale al ng-if de AngularJS)
- *ngFor: repite su elemento en el DOM una vez por cada item que hay en el iterador que se le pasa, siguiendo una sintaxis de ES6. (equivale al ng-for de AngularJS)
A nivel de código, los utilizaríamos así:
<div *ngFor="let todo of todos"></div>
<todo-detail *ngIf="selectedTodo"></todo-detail>
Directivas Atributo
Las directivas atributo alteran la apariencia o el comportamiento de un elemento existente en el DOM y su apariencia es igual a la de atributos HTML.
Las directivas Atributo alteran la apariencia o comportamiento de un elemento del DOM
Veamos las directivas atributo más típicas:
ngModel:
Implementa un mecanismo de binding bi-direccional. El ejemplo típico es con el elemento HTML <input>
, donde asigna la propiedad value a mostrar y además responde a eventos de modificación.
<input [(ngModel)]="todo.subject" >
ngClass:
Esta directiva permite añadir/eliminar varias clases a un elemento de forma simultánea y dinámica. El ejemplo es algo más complejo.
Por un lado, necesitaremos un método en nuestro componente que gestione el estado de las clases CSS que queremos aplicar a nuestro elemento, por ejemplo el siguiente:
setTodoClasses(){
let classes = {
pending: !this.isDone, //true
done: this.isDone, //false
important: this.isImportant //true
};
return classes;
}
Entonces en el template podemos utilizar la directiva NgClass
y la vinculamos a nuestro método setTodoClasses
mediante property binding:
<div [ngClass]="setTodoClasses()">Este ToDo es importante y está pendiente</div>
ngStyle:
De forma análoga a ngClass
, esta directiva te permite asignar varios estilos inline a tu elemento. Veamos:
//in the component
setStyles(){
let styles= {
'text-decoration': this.isDone ? 'line-through' : 'none',
'font-weight': this.isImportant ? '600' : 'normal',
};
return styles;
}
<!--in template-->
<div [ngStyle]="setStyles()"></div>
Esto ha sido todo por hoy, recuerda que puedes ver el código completo en el repositorio de GitHub.
¡Saludos!
[…] Data Binding […]
Gracias por compartir, todo excelente. 🙂
[…] Data Binding […]