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 profundidad las principales directivas de componentes. A modo de repaso vamos a repasar nuevamente dichas directivas:

– Directivas de tipo atributo: se aplican como atributos a los elementos HTML. Modifican el DOM pero sin ser capaces de crear y destruir el elemento HTML sobre el que se aplican. Las directivas de tipo atributo están formadas por:

      • [ngStyle]: nos permitirán cambiar las propiedades del elemento HTML seleccionado.
      • [ngClass]: nos permitirán agregar clases dinámicamente sobre el elemento HTML seleccionado.

Directivas de tipo atributo:

[ngStyle]:

[ngStyle] nos permitirán cambiar las propiedades del elemento HTML seleccionado.

Antes de ngStyle vamos a ver Style Biding

Si realizamos una DIV podemos utilizar Style Binding para añadir propiedades a nuestro elemento DIV mediante a las cuales modificaremos el estilo de nuestro elemento. Estás propiedades tendrán distintos valores en función de si una condición (en nuestro caso una variable) se resuelve a true or false. Para realizar la asignación de un valor para dicha propiedad u otro utilizamos el operador ternario (condición ? valorTrue: valorFalse).

Si nos fijamos para cada propiedad tenemos que añadir un nuevo [] junto al nombre de la propiedad [style.nombrePropiedad]

Vamos a ver unos ejemplo con varias propiedades:

Ejemplo 1:


Ejemplo 2:

Vamos a ver otra manera de realizar esto mediante a la directiva ngStyle. Para ello:

Pero si miramos la consola de VSC podemos ver que no se ha realizado la transpilación correctamente, esto se produce debido que para poder trabajar con ngStyle primeramente necesitamos realizar un import. Con el fin de evitar el siguiente error: Exception: Can’t bind to ‘ngStyle’ since it isn’t a known native property

Para ello, importamos CommonModule (engloba ngStyle, classStyle, etc.) dentro de  nuestro modulo principal:

Y ahora si que se nos muestra correctamente:

Hasta ahora, hemos visto como trabajar con ngStyle pero nos faltaría añadirle el operador ternario para poder evaluar una condición (en nuestro caso una variable booleana) que retornará true or false. Mediante a la cual podamos trabajar con dos valores para las propiedades. Vamos a ello:

Si ahora podemos la variable a true, podemos ver que se invierten las propiedades del DIV1 realizado con Property Binding y el DIV2 realizado con [ngSytle]:

Ejemplo 3:

Vamos a mejorar el ejemplo que ya vimos en el artículo anterior de directivas estructurales:

Vemos que podemos aplicar ngStyle sobre el ejemplo que ya vimos de las cartas:

O incluso mostrar colores aleatorios para los tipos de naipe:

Si la variable está en false, se verán todos de color negro:

En cambio, si la variable está en true, podemos ver que los elementos cambian de color a un color hexadecimal aleatorio:

Si nos fijamos, nos funciona correctamente, pero en la consola nos aparece el error: ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: ‘#1219f2’. Current value: ‘#74207a’.

ExpressionChangedAfterItHasBeenCheckedError se produce cuando Angular analiza una expresión de nuestro HTML y detecta que ha cambiado después de que la haya verificado.
Este error solo se produce en el modo de desarrollo y por una buena razón; a menudo es una señal de que debe refactorizar su código, ya que Angular le advierte que este cambio en su expresión no se detectará al habilitar el modo de producción .
Una de las razones por las que el modo de producción es más rápido que el modo de desarrollo es que Angular omite algunas comprobaciones (por ejemplo, la detección de cambios después de que la vista sea iniciada AfterViewInit) que se realizan en el modo de desarrollo. Eso significa que el código que funcionará bien en el modo de desarrollo no funcionará en el modo de producción.

La solución más sencilla que existe para este error es:

Cambiar la estrategia de detección de cambios de componte a onPush (detectará/analizará los cambios en el cambio de objeto y no en el cambio de valor).

Si ahora actualizamos la página podemos ver que no nos muestra el error:

La potencia es esto es que podemos desactivar por ejemplo los 3 primeros LI y que se muestren random y hacer que solamente el 4 muestre un color aleatorio:

[ngClass]:

ngClass nos permitirán agregar clases dinámicamente sobre el elemento HTML seleccionado.

Ejemplo1:

Para empezar, vamos a partir del siguiente ejemplo sobre el que trabajamos con el atributo class y sobre el que hemos aplicado múltiples clases que tenemos definidas dentro de la hoja de estilos del CSS:

Si vamos al navegador, podemos ver el resultado:

¿Cómo pasamos esto a nuestra directiva [ngClass]? Pues muy sencillo, de la siguiente manera:

Si nos da el error: The class ‘AppComponent’ is listed in the declarations of the NgModule ‘AppModule’, but is not a directive, a component, or a pipe. Either remove it from the NgModule’s declarations, or add an appropriate Angular decorator.

Necesitamos importar CommonModule (engloba ngStyle, classStyle, etc.) dentro de nuestro modulo principal:

Podemos ver que el resultado será idéntico al anterior:

Otra opción para trabajar con [ngClass] sería utilizar un array de la siguiente manera:

Incluso desde nuestro TS sin problema:

Ejemplo2:

Pero realmente esto no nos supone un cambio tan significativo a lo que estábamos haciendo con nuestro atributo class. Vamos a ver otro ejemplo donde sí que nos añade el dinamismo del que hablábamos en su definición teórica:

Ahora podemos desactivar cualquiera de las clases desde nuestro TypeScript. Vamos a desactivar por ejemplo el color de la fuente y el del fondo.

Ejemplo 3:

Dentro del ngClass podemos activar o desactivar las clases en función de un condición. Vamos a ver un ejemplo:

Y podemos ver que el resultado es el siguiente:

Las condiciones que hemos verificado son:

– En la condición color-fondo analizamos si los elementos del array son mayores que 5. Si añadimos más elementos al array podemos ver que el fondo cambia a rojo:

– En la condición del color-fuente analizamos si el array tiene elementos. Podríamos hacer lo mismo mediante a frutas.length>0 pero realmente si no existe elementos en el array el *ngFor no lo recorrerá y por tanto podemos poner un true directamente y lo hacemos aún más fácil.

Si por ejemplo añadimos el nombre de la fruta al LI y está en true:

Si ponemos false No hacen falta las comitas » vemos que el color del texto cambia a negro:

– En la condición del tamanyo-fuente si el elemento 1 es manzana roja.

Hemos utilizado el elemento 0 que aunque esto es bastante peligroso ya que si intentamos acceder al elemento 110 del array (que no existe) vemos que provoca un error:

Si recorremos el elemento 0, aunque no exista no entrará en el if y por tanto no dará problemas. Pero podría dárnoslo si no existe la propiedad name. Así que esto era más para ver este ejemplo que una buena práctica.

– En la condición del border-margin analizamos si 5 es más grande que las frutas si tenemos 4 elementos en el array vemos que devuelve un borde:

En cambio si supera los 5 elementos nuestro array la condición será falsa y por tanto no se mostrará:

Ejemplo 4:

En este ejemplo final nos vamos a complicarnos un poco más la vida y para ello vamos a realizar un ejemplo en el que recorreremos una lista de objetos analizando si los LI son o impares con el fin de activar solamente algunas de las clases para cada uno. E incluso activar una clase para ambos:

El resultado será:

Espero que os haya gustado. Hasta la próxima ¡Un saludo!