En el artículo de Introducción a las directivas y tipos de directivas en Angular ya estubimos viendo como subdividimos a las directivas e hicimos una explicación principalmente teórica sobre los tipos de directivas disponibles en Angular.

En este, tal y como os prometí nos vamos a centrar en la práctica, explicando con produnfidad las principales directivas de tipo estructurales. A modo de repaso vamos a repasar nuevamente las directivas estructurales:

– Directivas de tipo estructural: Cambian el DOM, y el elemento HTML al que se le apliquen. Y nos permiten analizar una condición y en función de si dicha condición es verdadera o falsa nos va a permitir mostrar / ocultar elementos del DOM.

Las directivas estructurales están formadas por:

      • *ngIf o [ngIf]: permite evaluar de forma condicional una condición que devolverá un resultado booleano (true or false) y dicho  resultado se suele utilizar con la finalidad de mostrar u ocultar una información.
      • *ngFor o [ngFor]: permite iterar una array, objeto, etc. normalmente con el fin de insertar cada uno de los elementos contenidos en su interior.
      • *ngSwith o [*ngSwith] + *ngSwitchCase o [ngSwitchCase]: permite evaluar una expresión mediante a una sucesión de conficiones principalmente se utiliza cuando necesitamos analizar múltiples y solo queremos ejecutar una en específico.
      • Existen más directivas de este tipo (aunque no las veremos en este artículo) como pueden ser ngPlural (permite agregar o remover elementos del DOM, basado en un valor numérico), ngTemplate (es un template en Angular cuyo contenido puede reutilizarse en otros templates), ngComponentOutlet (nos permite crear componentes dinámicos)…

Directivas de tipo estructural:

*ngIf / [ngIf]:

*ngIf nos permite evaluar una condición y en función de si dicha condición devuelve true or false (verdadera o falsa) nos va a permitir mostrar / ocultar elementos del DOM.

Vamos a ver unos ejemplos:

– Ejemplo 1:

Un div que solo se mostrará si es cierta la variable saludo:

La directiva ngIf no oculta los elementos con CSS. Sino que los agrega y los elimina físicamente del DOM. Podemos confirmar todo esto utilizando las herramientas de desarrollo del navegador para inspeccionar el DOM.

– Ejemplo 2:

Un login, para ello, vamos a utilizar !login cuando el usuario no este logeado y login para cuando el usuario este logeado. Así, si el login es igual a true aparecerá Bienvenido user07142 y en caso contrario, un mensaje de que iniciemos sesión:

– Ejemplo 3:

También podríamos hacer un nglf – then y else por ejemplo si tenemos en unos productos comprados para las meriendas podemos comprobar si están disponibles o no:

Una opción para realizar lo mismo pero mucho más elegante podría ser:

Hasta aquí hemos desarrollado un ejemplo normal con dos condiciones de *ngIf, pero podemos utilizar *ngIf Else.

Para ello, tendremos que apoyarnos de ng-template acompañado de un Template Variable una plantilla para poder mostrar el resultado en la pantalla de la siguiente manera:

Hasta ahora hemos usado solamente una ng-tempalte pero podemos utilizar *ngIf junto a then y else de la siguiente manera:

Si os fijáis, necesitamos dos ng-template con dos #templateVariable sobre las que hacemos referencia desde nuestro *ngIf gracias a then (si es verdadera) y a else (si es falsa).

Atributo Hidden

Si escribimos dos DIVs podemos ver que se muestran y se visualizan por la pantalla:

Si a uno de los DIVs le aplicamos el atributo hidden (oculto) podemos ver que desaparece de la pantalla pero que no desaparece de nuestros elementos en el inspector (solamente lo oculta):

También podemos utilizar Property Binding y englobar a hidden con ello. Y vemos que si el elemento no es igual a 0 la condición sera true y por tanto, dicho div se muestra por pantalla:

Podemos hacerlo también analizando las dos condiciones, y podemos ver que el div dos es true y por tanto se oculta:

Si añadimos elementos al array, la condición del div1 será true y por tanto se ocultará:

Si analizamos un div oculto con *ngIf vs un div oculto con hidden, podemos observar que *ngIf elimina el elemento pero en cambio el atributo hidden lo carga pero lo oculta en la ventana pero no en el inspector.

Por lo que, ahora que sabemos las diferencias, si queremos ocultar un elemento hasta en el inspector del navegador utilizaremos *ngIf.

Y en cambio, si queremos ocultar un elemento pero que sea visible en el inspector de elementos utilizaremos hidden.

Lo importante de todo esto, es que utilizan hidden afectará más al rendimiento. Ya que el componente o elemento HTML sigue escuchando eventos, y sigue adjunto al DOM. Y Angular sigue buscando cambios que puedan afectas a los enlaces de sus datos. Independientemente de si el componente o elemento es visible o no, lo sigue haciendo.

*ngFor / [ngFor]:

ngfor nos permite hacer un bucle, es decir iterar una array, objeto, etc. normalmente con el fin de insertar cada uno de los elementos contenidos en su interior.

*ngFor sobre un Array:

Si recorremos un array manualmente por ejemplo nos podremos dar cuenta de lo pesado que esto se hace:

En el caso de que tengamos muchos elementos en nuestro array requeriría un gran esfuerzo. Y si por ejemplo borramos un elemento del array sin eliminar el LI del template, podemos ver que se muestra vacío y tendríamos que eliminar el LI .

En la actualidad, tenemos que buscar automatizar al máximo las cosas y por ello, esta manera de trabajar no es viable. Lo correcto para que esto sea mantenible sin nos suponga un gran esfuerzo y para ello, vamos a utilizar un bucle y que sea él sea el encargado de mostrar todos los elementos de un array automáticamente actualizando la template si se encuentran cambios en el array:

*ngFor sobre un objeto

Si repetimos el mismo proceso sobre un listado de objetos, podemos ver que el resultado no es el esperado:

Esto se produce debido a que estamos seleccionando la propiedad que queramos mediante a String Interpolation:

Ejemplo de cambios a tiempo real al añadir otro objeto

Anteriormente hemos hablado de detención de cambios automáticamente. Vamos a verlo mediante a un ejemplo:

Para ello, recordad que necesitamos importar FormsModule para poder trabajar con [(ngModule)]

Si añadimos los valores y pulsamos sobre añadir:

Vemos como se nos añaden y además nos aparece un mensaje por la consola del inspector:

También podemos hacer el eliminar. Para ello, podemos hacer el evento click sobre un botón dentro de nuestro li y pasarle como parámetro el objecto actual. Posteriormente hacemos un indexof de la carta y así ya tenemos indice del objeto:

Si ahora hacemos click, aún no nos elimina el objeto, pero ya tenemos el array y el indice a eliminar:

Ahora solamente nos falta eliminar el objeto para ello:

Si ahora eliminamos el 3 elemento (aunque tengamos 4 elementos recordad que los arrays empiezan siempre por 0):

Podemos ver que ha desaparecido el elemento 3 y que nos ha informado de ello la consola del navegador:

*ngSwith o [*ngSwith] + *ngSwitchCase o [ngSwitchCase]:

ngSwitchCase, nos permite evaluar una expresión mediante a una sucesión de condiciones principalmente se utiliza cuando necesitamos analizar múltiples y solo queremos ejecutar una en específico.

Ejemplo 1:

Si tenemos los iconos de nuestras cartas de una baraja dentro de un objeto y los queremos mostrar por pantalla y además de mostrar el icono añadir el tipo (Corazones, Picas, Diamante o Trébol) y el color (Rojo o negro) ya que tenemos dicha información dentro del objeto.

Para realizarlo, necesitamos recorrer los elementos con un bucle en el que añadiremos el condición a evaluar mediante a [ngSwitch] en este caso analizaremos la única que tenemos (el icono).

Y además, de este ngSwitch donde analizamos la condición, vamos a añadir li con cada uno de los casos.

El resultado será:

Ahora, además vamos a cambiar el color de cada LI dependiendo del icono. En este caso, hemos cambiado tantos el estilo de ambos. Ya que con ello, preveemos si en un futuro alguien modifica las hojas de estilo tocando y modifica un estilo que afecte a la fuente general no nos afectará a nuestros LI.

El asterisco * vs corchetes []

Cuando trabajamos sobre las directivas de tipo estructurales, hemos visto que tenemos dos opciones usar el asterisco * o utilizar cochetes []. Un ejemplo de ello puede ser: *ngIf o bien utilizar [ngIf].

En el primer caso ¿No os preguntáis para que sirve dicho asterico? ¿O el porqué es necesario?

El asterisco no es nada más y nada menos que lo que se conoce en JavaScript como «syntactic sugar» que podría traducirse como «azúcar sintáctico». Con este término, nos en este caso en concreto nos referimos a que realmente JS (en nuestro caso más concretamente TS) traduce nuestro div por lo siguiente:

En la sintaxis desacuzarada podemos ver que:

  • Que la directiva .*ngIf se engloba dentro de <ng-template>[ngIf]
  • El <div> se ha introducido en el interior del elemento <ng-template>.

Por lo que el div  *ngIf  (con syntactic sugar) será «desazucarado» siendo traducido internamente por Angular transformándose en una envoltura a nuestro elemento antitrión (el DIV) con un <ng-template>.

Aunque ambas alternativas son validad para Angular, la sintaxis del asterisco (*) es más clara que la forma desazucarada.

Las directivas NgFor y NgSwitch, también siguen el mismo patrón.

Espero que os haya gustado el artículo. Un saludo y hasta la próxima