¿Cómo usar Expresiones en Enlazado de Eventos (Event Binding) de Angular?

¿Cómo usar Expresiones en Enlazado de Eventos (Event Binding) de Angular?

En contraparte con las expresiones de plantillasque se usan en las interpolaciones y Property Binding, una Expresiónde Enlazado de eventos (Event Binding)tiene un efecto colateral, este efecto sin embargo, es deseado, es el objetivo de un evento, modificar el estado de la aplicación a través de las acciones del usuario.

Por la explicación anterior, se les llama también expresiones de estado, En el siguiente ejemplo podemos ver la invocación a un método, la sintaxis para Event Bindinges (evento)="expresión":

<button (click)="cambiarNombre()">Voltear nombre</button>

La sintaxis para las expresiones en Enlazado de eventos como las expresiones de plantillases parecida a las expresiones de Javascript normales, pero tiene ciertas limitaciones. No está permitido:

  • El operador new
  • Los operadores ++y --
  • Los operadores de asignacion (+=,-=, *=, etc), OJO: el operador =SI está permitido.
  • Los operadores a nivel de bits |y &
  • Los operadores de expresiones de plantillas:  Operador de Tuberia |Operador de Guardia contra valores null o indefinidos, muy util en acceso a datos, ?.Operador para vereficar referencia NO Nulla, ! 

A diferencia de las expresiones de plantillas que se utilizan en interpolación y Property Binding, las expresiones de estado aceptan:

  • El operador de asignacion =
  • Expresiones consecutivas como operacion = operacion + 1;resultado = operacion * 2

Aquí esta un ejemplo en acción, revisa el archivo src/app/app.component.ts, puedes dar click en los botones azules botho previewpara ver el código en acción.

¿De dónde se obtienen los valores de las expresiones de enlazado de eventos?

Al igual que las expresiones de plantillas, las expresiones de estado normalmente obtienen sus valores de los miembros de la clase del componente. Por ejemplo, las propiedades nombrey resultadoen el ejemplo anterior.

Y al igual que las expresiones de plantilla, se pueden usar las propiedades o variables de plantillasen el contexto de la plantilla misma.

Variables de input y de referencia

<p *ngFor="let persona of gente">
 <input #nombre [value]="persona.nombre" (input)="persona.nombre = $event.target.value"/>
 {{persona.nombre}}
 <button (click)="eliminar(nombre.value, $event)">Eliminar</button>
</p>

Aquí se utiliza la variable de input personaque es un objeto y se accede a su propiedad nombreen la Expresión de Estado (input)="persona.nombre = $event.target.value"

También tenemos la variable de referencia #nombrela cual se utiliza en la expresión de estado (click)="eliminar(nombre.value, $event)".

En ambos casos vemos la propiedad de plantilla $event, la cual contiene la referencia al evento y elemento relacionado. Se accedió al valor de los input a través de $event.target.value.

También mandamos todo el objeto $eventen la expresión de estado para eliminar a una persona (click)="eliminar(nombre.value, $event)", y el método eliminar de la clase del componente imprime el tipo de evento en un alerta.

Ejemplo en acción:

¿Cómo enlazar propiedades entre componentes? Property Binding Angular

¿Cómo enlazar propiedades entre componentes? Property Binding Angular

El enlazado de propiedades o Property Binding en ingles, es una forma fácil y rápida en que se puede definir una propiedad a un componente de una aplicación en angular y actualizar esta propiedad si se detecta un cambio en el origen de la información.

El enlazado de propiedades se puede definir a un elemento nativo HMTL, un componente o una directiva.Para definir una propiedad se utilizan Expresiones de plantillas, te recomiendo que leás esta publicación ¿Cómo usar Expresiones en Interpolación y Property Binding de Angular?.

Uno de los ejemplos más sencillos es el enlazado de la propiedad src, en la sección Contenido segurode esta publicación podrás ver el ejemplo en acción con plunker:

<img [src]="persona.photoURL">

La etiqueta imgtambién tiene un atributo src, pero aquí vale la pena indicar que las propiedades y atributos de un elemento no son lo mismo. El Enlazado de Propiedades se aplica a las propiedades mismas, no a los atributos.

Los atributos a veces se ocupan para reflejar el estado de un elemento o componente, pero un atributo es útil para declarar información inicial del elemento en el código HTML, una propiedad forma parte de la instancia del elemento.

Para probar que son diferentes, si quieres obtener el valor de un atributo se utiliza elemento.getAttribute(nombreAtributo), para obtener el valor de una propiedad se utiliza elemento.propiedad.

Para definir un atributo se utiliza elemento.setAttribute(nombreAtributo, valor), para definir una propiedad se utiliza elemento.propiedad = valor.

Los atributos se guardan en una propiedad elemento.attributesde la instancia del elemento o componente. Para entender esto de atributos y propieades te recomiendo la sección sincronización de atributos y propiedades.

Ahora veamos como podemos habilitar y deshabilitar un <input>a través de la propiedad disabled:

<input [disabled]="isDisabled" value="Hola"/>

Existe otra notacion para enlazar propiedades, bind-propiedad="expresion":

<input bind-disabled="isDisabled" value="Hola"/>

Otro ejemplo interesante es definir el valor classde un elemento a traves de la directiva ngClass:

<p [ngClass]="clases"></p>

Aqui la pregunta es, ¿Cómo sabe angular que ngClasses una directiva y no una propiedad?

En otra publicación veremos como crear una directiva, por el momento solo toma en cuenta que la forma en que las directivas estan creadas permite a angular revisar si es una directiva o no. Angular antes de intentar hacer un property binding revisa si existe una propiedad ngClassen la directiva o en el elemento que se esta aplicando. En el caso anterior, los elementos nativos no tiene la propiedad ngClass, los elementos html tiene la propiedad classNamey classList, pero en este caso podemos decir que [ngClass]es un directiva.

Contenido seguro

Angular hace su trabajo en mantener tu codigo seguro, aquí un ejemplo usando property binding:

cuidado: string = '<script>alert('Este código es peligroso')</script>';

Comunicación entre componentes

El enlazado de propiedades es muy útil en la comunicación de Padre a hijo de componentes, veamos un ejemplo concreto, tenemos al componente padre pb-person-list, el cual contiene un listado de componentes hijos de tipo pb-persona.

  • Componente padre:
    • src/app/pb-person-list/pb-person-list.component.ts
    • src/app/pb-person-list/pb-person-list.component.html
  • Componente hijo:
    • src/app/pb-person-list/pb-person.component.ts
    • src/app/pb-person-list/pb-person.component.html

El componente padre contiene un arreglo de personas, este arreglo se bindea a través de la directiva *ngFory Property Bindingcon la propiedad persondel componente hijo.

Aquí hay algo de suma importancia, para que en el componente hijo se pueda realizar el Enlazado de Propiedades, se define la propiedad personcon el decorador @Input('alias'), a si mismo la propiead persondentro del componente es utilizada como persona, pero desde el exterior se bindea con [person]="expresion"', esto es así debido a el alias que definimos en @Input('person) persona: Object. El alias es opcional, si no lo tiene, entonces se bindea con [persona]="expresion"

¿Cómo usar Expresiones en Interpolación y Property Binding de Angular?

¿Cómo usar Expresiones en Interpolación y Property Binding de Angular?

Es importante saber que son las expresiones de plantillas, estas se utilizan en las interpolaciones y en el Enlazado de propiedades (Property Binding).

Cuando creas un componente, se utiliza HTML para crear su plantilla, esto es bueno, no tienes que aprender mucho de otra sintaxis para plantillas, aun así angular incorpora una pequeña sintaxis, que, aunque pueda ser nueva, es de gran utilidad y en esta publicación veremos expresiones de Javascript, interpolación y property binding en las plantillas de angular.

En las plantillas de angular cualquier elemento HTML es valido, a excepción de elementos como <html>, <head>, <base>, los cuales no tiene que estar en una plantilla de angular porque las plantillas de angular se “dibujan”dentro de la etiqueta <body>.

Otra excepción de suma importancia es la etiqueta <script>, esta etiqueta no se debe usar en las plantillas por el riesgo que se corre a ataques de XSS. Afortunadamente Angular previene XSS a través de sanitización, esta técnica convierte texto potencialmente ejecutable (código no deseado) a texto totalmente seguro.

¿Qué son las expresiones de plantillas?

Las expresiones de plantillas no son más que expresiones de Javascript normales con ciertas limitaciones. Veamos dos ejemplos:

En Interpolación se utiliza la sintaxis {{expresion}}:

<h3>2 + 2 es igual a {{2 + 2}}</h3>

El resultado es:

<h3>2 + 2 es igual a 4</h3>

En enlazado de propiedades se utiliza la sintaxis [propiedad]="expresion":

<h2 [hidden]="oculto">Ejemplo Enlazado de propiedades</h2>
<input [hidden]="oculto" value="Este es un input oculto">

En el ejemplo, debido que la propiedad ocultoes un boleano igual a true, el h2y el inputpermanecen ocultos. El mismo resultado se obtiene si usamos el comparador de igualdad:

<h2 [hidden]="oculto === true">Ejemplo Enlazado de propiedades</h2>
<input [hidden]="oculto === true" value="Este es un input oculto">

Vemos que dentro de la sintaxis de doble llaves existe una operación de suma y usamos el operador de igualdad en oculto === true, es decir, podemos utilizar Expresiones de Javascripten nuestras plantillas, aunque podemos utilizar expresiones de Javascript, no todo está permitido.

Las expresiones Javascript que producen efectos colaterales no se deben utilizar y NO están permitidas:

  • Las asignaciones (=,+=,-=, *=, etc)
  • El operator new
  • Las Expresiones consecutivas con ;o ,. Ejemplo {{1+1;2+2}}
  • Los operadores ++y --
  • Los operadores a nivel de bits |y &

Una característica importante en las expresiones de plantillas y que es distinta de las expresiones Javascript normales es que se pueden utilizar los siguientes operadores, pero ojo, no son operadores a nivel de bits:

  • Operador de Tuberia |
  • Operador de Guardia contra valores null o indefinidos, muy util en acceso a datos, ?.
  • Operador para vereficar referencia NO Nulla, !

Estos tres últimos operadores los veremos a detalle en otra publicación.

Interpolación

La interpolación nos permite obtener información en una aplicación, genera un enlacecon el origen de la información, es decir, si los datos de origen cambian, la interpolación actualiza ese cambio en la vista. En otras palabras, reacciona al cambio de datos.

Ejemplo, contenido de src/app/app.component.html:

<div>
  <h2>Hola {{nombre}}</h2>
  <h2>{{"cadena".split('').reverse().join('')}}</h2>
  <h2>{{false ? 'SI' : 'NO'}}</h2>
  <img src="{{logo}}">
  <h3>2 + 2 es igual a {{2 + 2}}</h3>
  <h2 [hidden]="oculto">Ejemplo Enlazado de propiedades</h2>
  <input [hidden]="oculto" value="Este es un input oculto">
  <h2 [hidden]="oculto === true">Ejemplo Enlazado de propiedades</h2>
  <input [hidden]="oculto === true" value="Este es un input oculto">
  <button (click)="cambiarNombre()">Voltear nombre</button>
</div>

Ejemplo en acción, revisa el archivo src/app/app.component.ts:

En el ejemplo tenemos un componente llamado my-appdefinido en el archivo src/app/app.component.ts, la plantilla del componente está definida en la propiedad templateUrldel decorador @component, carga un arhivo html externo.

Podemos ver que cuando damos clic en el botón Voltear textola propiedad nombrees cambiada invirtiendo los caracteres, se invierte los caracteres a través del método cambiarNombre. Y la reacción a este cambio esta enlazado con la interpolación {{nombre}}.

También se puede utilizar interpolación en atributos, en el ejemplo anterior para mostrar la imagen se utilizó:

<img src="{{logo}}">

Otro ejemplo:

<h3>2 + 2 es igual a {{2 + 2}}</h3>

¿De dónde se obtienen los valores de las expresiones de plantilla?

Normalmente los valores estan definidos en el componente como vimos en el anterior ejemplo, nombrey logoestán definidos como miembros de la clase y en el constructor se les define su valor.

Pero también se puede definir propiedades en el contexto de la plantilla llamadas variables de plantillas, existen dos tipos de estas variables:

  1. Variables de input
  2. Variables de referencia

Variables de input

<div *ngFor="let persona of gente">
  <h3>{{persona.nombre}}</h3>
</div>

personaes la variable de input usada en la directiva *ngFor

Variables de referencia

<input #varReferencia value="Hola">
{{varReferencia.value}}

En este otro caso se ocupa el carácter #y luego el nombre de la variable de referencia que deseas crear. Con esto se puede utilizar la variable en interpolación como se ve en {{varReferencia.value}}.

La jerarquía o prioridad del valor final obtenido en las expresiones de plantillas es así:

  1. Variables en plantilla, input y de referencia.
  2. Directivas
  3. Componentes

Para ilustrar la prioridad, veamos el ejemplo, en la parte donde se utiliza la directiva *ngForpara recorrer el arreglo gente, ahí se define una variable de input persona, y después se accede a la propiedad nombre de cada persona, podemos notar que debido a la jerarquía arriba listada se tomo primero en cuenta la variable de plantilla personaantes que el miembro personadel componente. El miembro personaes un string “soy otra persona”y nunca se imprime dentro de la lista de personas.

Cuando uses una expresión de plantilla, sigue estos consejos:

  1. Tu expresión debe ser rápida de ejecutar porque no va a ser la única en toda tu plantilla. Si es necesario, considera guardar los resultados de las expresiones que se van a utilizar varias veces en la plantilla y asi la expresion no se ejecuta varias veces.
  2. Utiliza el principio de mantener todo estúpidamente simple, no uses complejas expresiones porque genera mucho ruido en la plantilla, para expresiones más complejas utiliza la clase del componente, y aún ahí considera el principio KISS (Keep It Simple, Stupid).
  3. Investiga el funcionamiento de detección de cambios de angular para mantener tus expresiones lo más eficientes posibles, en una futura publicación explicaré la detección de cambios y como nos ayuda a mejorar el rendimiento de nuestro aplicación.
¿Cómo implementar angular material design en 5 minutos?

¿Cómo implementar angular material design en 5 minutos?

En este post explicaré como crear la estructura básica del diseño de una aplicación con Angular y Angular material design. Angular material design es una colección de componentes visuales optimizados para una mejor experiencia de usuario y creación de interfaces gráficas.

Utilizarlo nos ahorra mucho tiempo creando y diseñando nuestros propios componentes, por lo que es una buena opción para acelerar las creación de aplicaciones web.

Primero vamos a crear una nueva aplicación con **angular-cli:

$ ng new basic-angular-material

Luego ejecutamos nuestra aplicación con ng serve:

cd basic-angular-material && ng serve

Nuestra aplicación se debería de ver así:

Ahora instalamos el paquete de Angular material:

npm install --save @angular/material @angular/cdk

Si te das cuenta, ademas de instalar el paquete de @angular/material, también instalamos el paquete @angular/cdk, este ultimo en versiones anteriores formaba parte del paquete de @angular/material, pero es tan útil en la creación de componentes que ahora es independiente y al serlo permite que otros desarrolladores se beneficien para crear sus propios componentes al mero estilo de angular material.

Como muchos componentes de angular material realizan animaciones para una mejor experiencia de usuario, si queremos que nuestros componentes tengan animaciones debemos instalar el paquete @angular/animationse importar el modulo BrowserAnimationModuleen nuestra aplicación.

npm install --save @angular/animations

En el archivo src/app/app.module.tsimporta el modulo de animaciones, lineas 7 y 16, en el código de ejemplo:

Ahora debemos incluir un tema para nuestra app, es requerido para la correcta visualización de la mayoría de los componentes. Debemos incluir la siguiente linea de código en el archivo /src/styles.css.

@import “~@angular/material/prebuilt-themes/indigo-pink.css”;

Para que los componentes reaccionen bien a eventos de touch en pantallas, necesitamos de la librería HammerJS, varios componentes utilizan HammerJS así que lo podemos instalar con el siguiente comando:

npm install --save hammerjs

En el archivo /src/main.tsimportamos la librería en la linea 8.

Importamos los módulos de Angular Material que vayamos a utilizar. Vamos a modificar el archivo src/app/app.module.tspara que quede como el código de abajo. Otra opción es crear un modulo nuevo donde importemos los componentes de angular material que vayamos a utilizar. En este ejemplo importamos los componentes en la linea 9.

Con todo lo anterior listo, podemos empezar a utilizar los componentes, vamos a modificar el contenido por defecto del template del componente principal que nos genera la herramienta de linea de comandos de angular-cli.

Versión final:

Nuestra app debe verse así:

Y cuando damos click(o touch) en el menú:

Para que tu app se vea de esta manera, sin espacios en blanco a los lados y la barra lateral a toda la altura del navegador web, tu archivo src/styles.cssdebe ser así:

Demo de interfaz gráfica para creación de encuestas. Angular 5 y Angular material design 5:

Angular: Hooks del ciclo de vida de un componente

Angular: Hooks del ciclo de vida de un componente

Introducción a los hooks de angular

Antes de empezar a describir los Hooks del ciclo de vida de un componente en angular quiero citar la definición de Hooking de wikipedia:

El término Hooking abarca una gama de técnicas utilizadas para alterar o aumentar el comportamiento de un sistema operativo, aplicaciones o de otros componentes de software interceptando llamadas de función o mensajes o eventos pasados entre componentes de software. El código que maneja tales llamadas de función, eventos o mensajes interceptados se le llama un Hook.

En angular tenemos estos hooks, que son funciones ejecutadas en puntos claves del ciclo de vida de un componente.

Tanto los componentes y las directivas pueden ejecutar estas funciones. Pero las directivas no ejecutan las funciones de color azul, las cuales son específicas de la vista y contenido de componentes.

Dado que normalmente se utiliza typescript en Angular para obtener el código javascript final. Vamos a implementar estos métodos utilizando la interfaz que le corresponde a cada uno. Todas estas interfaces están en el modulo @angular/core.

Por ejemplo, para implementar el método ngOnInit, debemos importar la interfaz OnInit:

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

El lenguaje de javascript no tiene interfaces, estas interfaces las agrega typescript para obtener un Javascript fuertemente tipeado y basado en clases. Aunque las ultimas versiones de javascript utilizan una sintaxis de clases casi idéntica, por detrás realmente son funciones y herencia prototipal.

Todos los hooks del ciclo de vida de un componente en acción

Más abajo tenemos ejemplos de todos los hooks en acción y están basados en el código de la documentación oficial de Angular. Para ver mejor el código y el funcionamiento en tiempo real, siempre puedes presionar este botón:

Existe un componente de tipo ParentComponent y otro ChildComponent. El ParentComponent se encarga de crear el ChildComponent, de esta manera será más fácil poder ver en acción los hooks. También se encarga de bindear la propedad name y actualizarla para poder ver el hook ngOnChanges.

Como te darás cuenta viendo el archivo /app/all/child.component.ts, este componente implementa todas las interfaces de los hooks.

Si presionas el botón Crear ChildComponent, el mensaje #1 es en el constructor del componente, el constructor normalmente se utiliza para definir valores iniciales simples, nunca pongas mucha lógica en el constructor. Además podemos notar que la propiedad name en este punto, aun no esta definida.

Después tenemos el mensaje #2, este es del hook ngOnChanges, aquí es cuando ocurre el enlazado de las propiedades con la nueva instancia de nuestro ChildComponent, en este punto la propiedad name ahora si esta definida.

Luego tenemos la ejecución de ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, ngAfterViewChecked en ese orden.

Ahora si presionas el botón Actualizar ChildComponent, se actualiza la propiedad name desde el ParentComponent, podemos ver como se ejecutan ngDoCheck, ngAfterContentChecked, ngAfterViewChecked, y otra vez ngOnChanges, ngDoCheck, ngAfterContentChecked y finalmente ngAfterViewChecked. Aquí podemos afirmar dos cosas:

  1. ngDoCheck, ngAfterContentChecked, ngAfterViewChecked se invocan en ese orden al detectar un cambio.
  2. También se ejecutan siempre tras un ngOnChanges pues se volvieron a ejecutar en ese mismo orden

Finalmente, si presionas el botón Destruir ChildComponent, los hooks ngDoCheck, ngAfterContentChecked, ngAfterViewChecked se vuelven a ejecutar, y además antes de destruir el componente totalmente, se ejecuta el hook ngOnDestroy.

Hooks ngOnChanges

Cuando se crea un componente lo primero que se ejecuta es el constructor de la clase del componente. Ahora bien, esto es totalmente normal en otros ámbitos. La creación de una nueva instancia de clase, así que realmente constructor no es un hook de angular.

ngOnChanges solo revisa los cambios de una propiedad input, esto es, todas las propiedades a las que se les aplica el decorador @input([alias]), que es la manera en que bindeamos o enlazamos propiedades de un componente padre a otro hijo usando esta sintaxis [habilidad]="expresion". Este patrón, de padre a hijo, nos permite obtener un mejor rendimiento en la detección de cambios entre componentes. Es por eso que en el código de los ejemplos siempre se utiliza un componente padre y un componente hijo. Los cambios se actualizan de padre a hijo.

En el ejemplo tenemos dos propiedades enlazadas [persona]="persona"y [habilidad]="habilidad", si cambiamos el valor de habilidad se dispara la ejecución de ngOnChanges en el componente hijo, sin embargo la propiedad persona.name no dispara el hook, esto pasa porque la detección de cambios comprueba la referencia de la propiedad persona y lo que se modifico fue la propiedad persona.name, por lo que la referencia al objeto persona nunca cambió.

Cada vez que se detecta un cambio, ngOnChanges recibe un objeto, el cual contiene todas las propiedades que cambiaron, y cada una de estas es de tipo SimpleChange conteniendo el valor anterior previousValue y el valor actual currentValue.

ngOnChanges puede detectar cambios en más de una propiedad @Input(), por lo que es muy útil para realizar múltiples operaciones en la información, como definir valores predeterminados, validar datos, transformarlos antes de ser utilizados por el componente y/o antes de ser visualizados por el usuario.

Hooks ngOnInit y ngOnDestroy

Hook ngOnInit

El hook ngOnInit se ejecuta una sola vez después de ngOnChanges y no se vuelve a ejecutar en el resto de vida del componente.

Una directiva puede tener hooks, esto se debe a que un componente es un tipo de directiva que tiene una plantilla html. Es decir, un componente es una directiva.

Dado que ngOnInit se ejecuta una sola vez después de ngOnChanges, es un buen lugar para:

  1. Agregar inicializaciones complejas.
    1. Como algún proceso asíncrono
    2. Obtener de un servicio datos para uso en el componente
    3. Subscribirse a un objeto para ser notificado de cambios, como los observables de RxJs, escuchar eventos del DOM
    4. Etcétera.
  2. Configuración de inicio debido a que ya se tienen los valores de las propiedades @inputs() gracias al hook ngOnChanges.

Cada vez que se presiona el botón Agregar Persona el hook ngOnInit se ejecuta, y cuando presionas el botón Resetear se ejecuta el hook ngOnDestroy justo antes de destruir a las elementos personas.

Hook ngOnDestroy

En este hook del ciclo de vida de un componente debería de ir todo el código de limpieza de un componente, justo antes de destruirlo.

También es un buen momento para notificar a otros componentes que va a ser destruido.

Es un buen punto donde liberar memoria, darse de baja de los Observadores como RxJS y los eventos del DOM. Detener los timers, dar de baja todos los callbacks enlazados a servicios. En general todo lo que consuma memoria y tiempo de ejecución.

Hook ngDoCheck

Este Hook del ciclo de vida de un componente se ejecuta después de cualquier ejecución de ngOnChange, y despues de ngOnInit, pero también se ejecuta después de eventos que pueden producir cambios, como por ejemplo el blur y focus de los inputs.

Dado que se ejecuta demasiadas veces, es muy costoso utilizar este hook, así que se debe usar con cuidado.

Para crear este ejemplo simplemente se implementó el método ngDoCheck en el componente hijo del código del hook ngOnChanges. Puedes probar cambiando datos y veras la ejecuciones de la función ngDoCheck.

ngOnChanges NO se ejecuta cuando modificamos una propiedad que no es un @input(), como pasa con la propiedad name del objeto persona, pero si se ejecuta el hook ngDoCheck. Puede ser útil para detectar cambios internos del componente, pero recuerda que tiene un costo alto de ejecución si deseas detectar muchas propiedades NO @inputsde tu componente.

También tenemos un elemento input dentro del componente hijo que esta enlazado a la propiedad [habilidad], esta es un @input, pero el cambio se realiza dentro del componente hijo, el componente padre no se entera de este cambio, por lo que aunque ngDoCheck se ejecuta, ngOnChanges no lo hace. Recuerda, la detección de cambios entre componentes se realiza de manera unidireccional, de padre a hijo.

Hooks AfterContentInit y AfterContentChecked

ngAfterContentInit se ejecuta una vez después del primer ngDoCheck y no se vuelve a ejecutar en todo el resto de vida del componente. ngAfterContentChecked se ejecuta después de cualquier ejecución de ngDoCheck en todo la vida del componente. Ambos se ejecutan después de que angular proyecta contenido externo en el componente.

Este contenido externo es proporcionado por el usuario del componente, similar a lo que se hace con el Light DOM de los componentes web nativos.

A lo anterior Angular le llama Proyección de contenido (Content projection), en AngularJS se conoce como transclusión. Para proyectar el contenido en el componente, se debe utilizar el tag <ng-content></ng-content>, esta etiqueta sería análoga a la etiqueta <slot> de los componenes web nativos.

Dentro del método ngAfterContentChecked se debe poder acceder al modelo o variables del contenido proyectado, para esto se debe utilizar el decorador @ContentChild([TipoDeHijo]), lo puedes ver en el archivo /app/after-content/after-content-child.component.ts.

// Para buscar contenido de tipo 'ChildComponent'(etiqueta lch-child)
@ContentChild(ChildComponent) contentChild: ChildComponent;

Hooks AfterViewInit y AfterViewChecked

Estos hooks son muy similares a ngAfterContentInit y ngAfterContentChecked, solo que se invocan después de ngAfterContentChecked, siguiendo el mismo patron, ngAfterViewInit se invoca una sola vez después del primer ngAfterContentChecked, y no se vuelve a invocar.

ngAfterViewChecked, se ejecuta después de cualquier invocación de ngAfterContentChecked, la diferencia entre ngAfterContentChecked es que estos hooks marcan el final de la composición de la vista de un componente y se define dentro del componente mismo, no desde el exterior, como vimos con ngAfterContentChecked y ng-content, por esta razón tiene similitud con el Shadow DOM de los componentes web nativos.

Si revisas el código del /app/after-view/after-view-child.component.ts, para acceder al modelo o variables de la vista interna (Vista de hijos o Child View), debemos utilizar el decorator @ViewChild([TipoDeHijo]):

// Para buscar view childs del tipo ChildComponent
@ViewChild(ChildComponent) viewChild: ChildComponent;

Otra cosa distinta a ngAfterContentChecked es que en ngAfterViewChecked no podemos cambiar el valor de inmediato de la propiedad comment enlazada con la vista, si lo haces, te saldrá un error como el siguiente:

Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: ''. Current value: 'Es un nombre muy grande'.

El error se debe que esté ultimo hook se ejecuta al final del ciclo de vida, entonces debe volver a pasar por ngOnChanges o ngDocheck para volver a renderizar la vista actualizada. La solución es actualizar la propiedad comment en una futura iteración del loop de Javascript. El setTimeout de this.logger.thick_then recibe una función, la cual se agrega a la cola de callbacks de javascript para ser escogida en una futura iteración del loop y esto le da el tiempo suficiente a Angular para actualizar la vista correctamente.

https://www.pensemosweb.com/javascript-event-loop-concurrencia-asincrono/
Loop de Javascript
es_MXES_MX