jueves, 22 de junio de 2017

Angular2: variable de referencia de templates

En la entrada de hoy vamos a ver las variables de referencia de plantillas.
Una variable de referencia de plantilla es una referencia a un elemento o directiva DOM dentro de una plantilla.
Se declara utilizando el prefijo # o bien la etiqueta ref- as dentro del elemento html. 
Asi por ejemplo, #edad, ref-edad serían declaraciones válidas.

Vamos a ver mejor su uso con un ejemplo. 

import { Component } from '@angular/core';

@Component({
selector: 'app-template-variable',
template: `
Nombre: <input type="text" #nombre placeholder="Introduce tu nombre">
<br> Edad: <input type="text" ref-edad placeholder="Introduce tu edad">
<br> Email: <input type="email" #email placeholder="Introduce tu email">
<br> <button (click)="mostrarDatos(nombre.value, edad.value, email.value)">
Mostrar datos</button>
`
})
export class TemplateVariableComponent {

mostrarDatos(nombre, edad, email) {
console.log(nombre);
console.log(edad);
console.log(email);
}

}

Como podemos observar en el código, hemos creado tres variables de referencia en la plantilla. Dos de ellas estan declaradas como #nombre y #email, y la restante con la otra forma permitida, es decir, con ref-edad.

Al hacer click en el botón, llamamos al método mostrarDatos que muestra en la consola los valores pasados como parametros al mismo. Estos parametros son los valores de los elementos del formulario.

Código disponible en https://gist.github.com/jorgetrigueros/951cc37f6d41b82403682ec7e82fef2a


lunes, 19 de junio de 2017

ngComponentOutlet: Cargando componentes dinámicamente

En la entrada de hoy vamos a ver cómo en Angular4 podemos cargar componentes de manera dinámica a través de la directiva NgComponentOutlet
Esta directiva proporciona un enfoque declarativo para la creación de componentes dinámicos.

Vamos a entenderlo mejor con un ejemplo. En esta ocasión vamos a crear un contenedor tab usando el framework css bulma

En primer lugar, instalamos bulma en nuestro proyecto: npm install bulma
Para usar bulma en nuestro proyecto creado con angular-cli, añadimos en el .angular-cli.json la hoja de estilos bulma.css

"styles": [
"styles.css",
"../node_modules/bulma/css/bulma.css"
],

Creamos un tab en bulma tal como se indica en la documentación http://bulma.io/documentation/components/tabs/

Nuestro tab va a ser similar al de la documentación,

<div class="tabs">
<ul>
<li class="is-active"><a (click)="changeComponent('Cine')">Cine</a></li>
<li><a (click)="changeComponent('Teatro')">Teatro</a></li>
<li><a (click)="changeComponent('Musica')">Música</a></li>
</ul>
</div>

Cada link del tab cargará un componente. Luego creamos los tres componentes que va a tener nuestra aplicación: CineComponent, TeatroComponent, MusicaComponent.

El componente vamos a cargarlo de manera dinámica, cuando se haga click en el link del tab, en un ng-container

<ng-container *ngComponentOutlet="component"></ng-container>

Mediante la directiva ngComponentOutlet, indicamos el componente que va a contener el container, luego la declaramos (en app.component.ts) y le asignamos un valor:

private component;
constructor() {
this.component = CineComponent;
}

Cuando se hace click en el título del tab, llamamos a la función changeComponent, que lo que hace es asignar el componente especificado en el parámetro.

changeComponent(componente) {
switch (componente) {
case 'Musica':
this.component = MusicaComponent;
break;
case 'Teatro':
this.component = TeatroComponent;
break;
default:
this.component = CineComponent;
break;
}
}


El resultado final quedará como se muestra a continuación:


En esta entrada hemos visto como la directiva NgComponentOutlet simplifica mucho la carga dinámica de componentes.
Espero que os haya gustado.

Código fuente disponible en: https://github.com/jorgetrigueros/ngComponentOutlet-ejemplo




viernes, 9 de junio de 2017

Directivas de atributo en Angular2 (2ª parte)

En la entrada anterior vimos como crear una directiva "tooltip" en Angular2 haciendo uso de la clase Rendered. En esta entrada vamos a hacer uso de la clase Renderer2 de Angular4.

En primer lugar, vamos a cambiar en la importación el Rendered por Rendered2.
Lo reemplazaremos también en el constructor.

Al realizar estos cambios, el compilador nos devolverá un error en las propiedades setElementAttributesetElementClass, ya que estas propiedades forman parte de la clase Rendered de Angular2 pero no de la clase Rendered2 de Angular4.

En la versión de Rendered2 en vez de setElementAttribute usaremos setAttribute (también podremos usar removeAttribute para eliminar el atributo) y en lugar de setElementClass usaremos addClass para añadir una clase css (también podemos usar removeClass para eliminar una clase existente)

Con estos cambios el código nos quedará así:

import { Directive, ElementRef, Renderer2, Input, OnInit } from '@angular/core';
@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective implements OnInit {
@Input() direccion: string;
@Input() texto: string;
constructor(private el: ElementRef, private renderer: Renderer2) {
}
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'aria-label', this.texto);
this.renderer.addClass(this.el.nativeElement, 'hint--' + this.direccion);
}
}

Vamos a mejorar un poco nuestra directiva asignando un valor por defecto a la propiedad "direccion" mediante un setter.

Para ello en primer lugar declaramos una propiedad con un valor por defecto:

private direccionDefault = 'top';

y posteriormente asignamos mediante un setter a dicha propiedad o bien el valor especificado, o en caso de que no se haya especificado en la propiedad "direccion" el valor por defecto.

@Input('direccion')
set direccion(value: string) {
this.direccionDefault = value || this.direccionDefault;
}


A la hora de añadir la clase "hint" pondremos el valor de direccionDefault:

this.renderer.addClass(this.el.nativeElement, 'hint--' + this.direccionDefault);

Si en la directiva no especificamos la dirección, tomará por defecto el valor "top", y si especificamos algún valor (left, right, etc.) mostrará el "tooltip" en la dirección especificada.

El código final queda así:

import { Directive, ElementRef, Renderer2, Input, OnInit } from '@angular/core';
@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective implements OnInit {
@Input() texto: string;
@Input('direccion')
set direccion(value: string) {
this.direccionDefault = value || this.direccionDefault;
}
private direccionDefault = 'top';
constructor(private el: ElementRef, private renderer: Renderer2) {
}
ngOnInit() {
this.renderer.setAttribute(this.el.nativeElement, 'aria-label', this.texto);
this.renderer.addClass(this.el.nativeElement, 'hint--' + this.direccionDefault);
}
}




lunes, 5 de junio de 2017

Directivas de atributo en Angular2

En esta entrada veremos que son las directivas de atributo en Angular2, como podemos usarlas, y crearemos una directiva para mostrar un "tooltip" en un elemento HTML.

Vamos allá...

Una directiva de atributo puede cambiar el comportamiento o la apariencia de un elemento del DOM o de un componente, y se parecen en cierto modo a los atributos de HTML

Vamos a verlo con un sencillo ejemplo. Crearemos una directiva para mostrar un tooltip en cualquier elemento HTML. Para crear nuestra directiva "tooltip" vamos a usar la librería css hint
Esta librería contiene las css necesarias para crear un tooltip únicamente con css, sin nada de código de script.

Haciendo uso de esta librería vamos a crear una directiva que haga básicamente lo mismo que ya hace hint. (es un ejemplo didáctico que nos servirá para ver que es una directiva y como podemos crearlas en Angular2).

Para crear una directiva (que llamaremos tooltip) con angular cli, tecleamos desde nuestra consola la intrucción ng generate directive tooltip o bien la versión reducida, es decir, ng g d tooltip

El código de la directiva que hemos creado con angular cli tiene el siguiente aspecto:

import { Directive } from '@angular/core';
@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective {
constructor() {
}
}

Vamos a importar ElementRef para seleccionar el elemento que será modificado y Renderer para visualizar el resultado de la modificación. Además, como veremos más adelante, vamos a querer que la propiedad que nos indica la posición del tooltip (top, bottom, left, right, etc.) sea indicada en el elemento html, así como el texto a mostrar en el tooltip. Es decir, nuestra directiva que la vamos a incluir en el app.component.html, tendrá un aspecto similar a:

<a href="#" appTooltip [texto]="'Prueba'" [direccion]="'top'">
Enlace con tooltip
</a>

En el ejemplo de uso anterior, la directiva appTooltip, mostrará un texto en una posicion especificada. Para mostrar tanto el [texto] como la [direccion] usaremos el decorador "input" (que se encuentra en @angular/core) de Angular

Por tanto tendremos algo como:

import { Directive, ElementRef, Renderer, Input, OnInit } from '@angular/core';
@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective implements OnInit {
@Input() direccion: string;
@Input() texto: string;
constructor(private el: ElementRef, private renderer: Renderer) {
}
ngOnInit() {}
}

Para mostrar un tooltip con hint, tenemos que usar la clase "hint--direccion" (por ejemplo, hint--top) y el texto a mostrar lo pondremos en el atributo aria-label del elemento HTML. Es decir, el uso seria algo similar a <.... aria-label="Thank you!" class="hint--bottom">hover over me.</...>

Por tanto, necesitamos por un lado asignar la clase 'hint' que hemos especificado con el Input direccion y por otro lado crear el atributo aria-label que contendrá el texto del tooltip.
Esto lo conseguimos mediante las siguientes intrucciones, que pondremos dentro del ngOnInit:

ngOnInit() {
this.renderer.setElementAttribute(this.el.nativeElement, 'aria-label', this.texto);
this.renderer.setElementClass(this.el.nativeElement, 'hint--' + this.direccion, true);
}

La propiedad renderer tiene entre otros los metodos setElementAttribute que establece el atributo especificado con el valor indicado (en nuestro caso el atributo 'aria-label' con el valor que pasamos en la variable "texto"), y otro metodo setElementClass para indicar la clase que queremos crear en el elemento obtenido mediante la instrucción el.nativeElement

La clase que crearemos será el resultado de concatenar "hint--" con el valor que indiquemos en "direccion", de tal manera que quedarán clases al estilo de "hint--top", "hint--left" etc.

El resultado después de lanzar el servidor con ng serve será similar al siguiente pantallazo:


En siguientes entradas veremos como podemos asignar valores por defecto a la dirección, y el uso de "renderer2" en Angular4.


Código fuente del ejemplo: https://github.com/jorgetrigueros/ng4-ejemplo-directiva

Bienvenidos a mi blog

Hola a todos, y bienvenid@s a mi blog.


Mi nombre es Jorge Trigueros, y  llevo dedicado profesionalmente al mundo del desarrollo desde hace ya más de 15 años.

A lo largo de mi vida profesional ha habido etapas en las que he sentido emoción ante algunas de las nuevas tecnologías que surgían en un determinado momento.

Recuerdo el entusiasmo que sentí cuando surgió asp.net. Era un mundo nuevo y lleno de posibilidades para los que veníamos del asp clásico y el "spaghetti code".

O cuando mi hermano me descubrió jQuery. esa librería que formaría parte necesaria de todos mis desarrollos web durante un buen tiempo. Como nos facilitaba las cosas!!!

Por supuesto la llegada de HTML5 y css3 me permitió ver a html con "otros ojos" :-)

También recuerdo la sensación de "poder" que sentí cuando escribí mi primer "todo list" con AngularJS Estaba emocionado!!. Y la emoción se convirtió en algo de "vértigo" inicial cuando tuve que abordar un proyecto de proporciones considerables en AngularJS 0.9

Por ultimo, recuerdo la sensación extraña que tuve al conocer Angular2 (por aquellos tiempos era la RC4, y en el momento de escribir este post va por la versión 4.0) ... pensé: "Madre mia!! lo fácil que era escribir un "hola mundo" en AngularJS y lo poco trivial que es en Angular2). Hasta que poco a poco, Angular me fue ganando, y hoy en día es el framework con el que me siento más cómodo.

Por supuesto he conocido otros frameworks o bibliotecas javascript, como VueJS, que sinceramente me encanta, React (he de reconocer que no lo controlo en exceso, y es una asignatura pendiente que tengo), o knockout, pero como he comentado anteriormente, con la que me encuentro más cómodo es con Angular. No quiero decir que Angular sea mejor o peor que VueJS u otras. Ahí no entro, y cada uno tendrá su opinión. Lo que digo únicamente es que me encuentro más cómodo.

Es por eso que después de intentarlo varias veces, me he decidido por fin a crear un blog donde compartir mis conocimientos, que voy adquiriendo día a día, dicho sea de paso, con todos vosotr@s.

Espero que les gusten los artículos que iré subiendo, intentaré que con cierta asiduidad, y al mismo tiempo espero y deseo vuestros comentarios, criticas y sugerencias.