Hooks de ciclo de vida

Intermedio
Angular
Angular
Actualizado: 24/09/2025

Hooks de Inicialización y cambios

Los hooks de ciclo de vida son métodos especiales que Angular ejecuta automáticamente en momentos específicos durante la vida de un componente. Estos hooks nos permiten ejecutar código personalizado cuando ocurren eventos importantes como la inicialización del componente o cuando cambian sus propiedades de entrada.

Los hooks de inicialización y cambios son los más fundamentales y utilizados en el desarrollo diario con Angular. Estos nos permiten reaccionar a los momentos clave del ciclo de vida del componente y ejecutar la lógica necesaria en el momento adecuado.

ngOnInit - Inicialización del componente

El hook ngOnInit se ejecuta una sola vez después de que Angular haya inicializado las propiedades del componente. Es el lugar ideal para realizar tareas de configuración inicial como cargar datos, configurar suscripciones o inicializar variables.

Para usar ngOnInit, debemos implementar la interfaz OnInit e importarla desde @angular/core:

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

@Component({
  selector: 'app-usuario',
  template: `
    <div>
      <h2>{{ titulo }}</h2>
      <p>Usuario: {{ nombreUsuario }}</p>
    </div>
  `
})
export class UsuarioComponent implements OnInit {
  titulo = '';
  nombreUsuario = '';

  ngOnInit() {
    // Se ejecuta después de la inicialización del componente
    this.titulo = 'Panel de Usuario';
    this.cargarDatosUsuario();
  }

  private cargarDatosUsuario() {
    // Simular carga de datos
    this.nombreUsuario = 'Ana García';
  }
}

El método ngOnInit es especialmente útil para operaciones asíncronas como peticiones HTTP o configuración de temporizadores:

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

@Component({
  selector: 'app-productos',
  template: `
    <div>
      @if (cargando) {
        <p>Cargando productos...</p>
      } @else {
        <ul>
          @for (producto of productos; track producto.id) {
            <li>{{ producto.nombre }}</li>
          }
        </ul>
      }
    </div>
  `
})
export class ProductosComponent implements OnInit {
  productos: any[] = [];
  cargando = true;

  ngOnInit() {
    // Simulamos una petición HTTP que tarda 2 segundos
    setTimeout(() => {
      this.productos = [
        { id: 1, nombre: 'Laptop' },
        { id: 2, nombre: 'Mouse' },
        { id: 3, nombre: 'Teclado' }
      ];
      this.cargando = false;
    }, 2000);
  }
}

ngOnChanges - Cambios en propiedades de entrada

El hook ngOnChanges se ejecuta cada vez que cambian las propiedades de entrada (@Input) del componente. Recibe un objeto SimpleChanges que contiene información sobre qué propiedades cambiaron, sus valores anteriores y actuales.

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-contador',
  template: `
    <div>
      <h3>Contador: {{ valor }}</h3>
      <p>{{ mensaje }}</p>
    </div>
  `
})
export class ContadorComponent implements OnChanges {
  @Input() valor = 0;
  mensaje = '';

  ngOnChanges(changes: SimpleChanges) {
    // Se ejecuta cada vez que cambia el valor de entrada
    if (changes['valor']) {
      const cambio = changes['valor'];
      const valorAnterior = cambio.previousValue;
      const valorActual = cambio.currentValue;
      
      if (!cambio.firstChange) {
        this.mensaje = `Cambió de ${valorAnterior} a ${valorActual}`;
      } else {
        this.mensaje = 'Valor inicial establecido';
      }
    }
  }
}

Un ejemplo práctico donde ngOnChanges es muy útil es cuando necesitamos procesar datos cada vez que cambian:

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'app-estadisticas',
  template: `
    <div>
      <h3>Estadísticas de Ventas</h3>
      <p>Total de ventas: {{ totalVentas }}</p>
      <p>Promedio: {{ promedio }}</p>
    </div>
  `
})
export class EstadisticasComponent implements OnChanges {
  @Input() ventas: number[] = [];
  
  totalVentas = 0;
  promedio = 0;

  ngOnChanges(changes: SimpleChanges) {
    if (changes['ventas'] && this.ventas.length > 0) {
      // Recalcular estadísticas cada vez que cambien las ventas
      this.calcularEstadisticas();
    }
  }

  private calcularEstadisticas() {
    this.totalVentas = this.ventas.reduce((sum, venta) => sum + venta, 0);
    this.promedio = this.totalVentas / this.ventas.length;
  }
}

ngDoCheck - Detección de cambios personalizada

El hook ngDoCheck se ejecuta en cada ciclo de detección de cambios de Angular. Es útil cuando necesitamos detectar cambios que Angular no puede detectar automáticamente, como modificaciones en objetos o arrays.

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

@Component({
  selector: 'app-lista',
  template: `
    <div>
      <h3>Elementos: {{ items.length }}</h3>
      <p>Última actualización: {{ ultimaActualizacion }}</p>
    </div>
  `
})
export class ListaComponent implements DoCheck {
  @Input() items: string[] = [];
  
  ultimaActualizacion = '';
  longitudAnterior = 0;

  ngDoCheck() {
    // Verificar si cambió la longitud del array
    if (this.items.length !== this.longitudAnterior) {
      this.ultimaActualizacion = new Date().toLocaleTimeString();
      this.longitudAnterior = this.items.length;
    }
  }
}

Buenas prácticas con hooks de inicialización

  • Usar ngOnInit para configuración inicial: Colocar la lógica de inicialización en ngOnInit en lugar del constructor del componente.

  • Implementar las interfaces correspondientes: Siempre implementar OnInit, OnChanges o DoCheck para mejor tipado y claridad.

  • Evitar operaciones costosas en ngDoCheck: Este hook se ejecuta frecuentemente, por lo que debemos ser cuidadosos con operaciones que consuman muchos recursos.

Estos hooks de inicialización y cambios proporcionan el control preciso que necesitamos sobre el comportamiento de nuestros componentes, permitiéndonos ejecutar código en los momentos exactos cuando el componente se inicializa o cuando sus datos cambian.

Hooks de contenido y vista

Los hooks de contenido y vista se ejecutan después de que Angular haya procesado el contenido proyectado y la vista del componente. Estos hooks son especialmente útiles cuando necesitamos interactuar con elementos del DOM o realizar operaciones que requieren que la vista esté completamente renderizada.

ngAfterContentInit - Contenido proyectado inicializado

El hook ngAfterContentInit se ejecuta una sola vez después de que Angular haya proyectado el contenido externo en el componente mediante ng-content. Este hook es ideal para acceder a elementos del contenido proyectado o realizar configuraciones que dependan de ese contenido.

import { Component, AfterContentInit, ContentChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-tarjeta',
  template: `
    <div class="tarjeta">
      <div class="cabecera">
        <ng-content select="[slot=titulo]"></ng-content>
      </div>
      <div class="contenido">
        <ng-content></ng-content>
      </div>
    </div>
  `,
  styles: [`
    .tarjeta { border: 1px solid #ccc; padding: 16px; }
    .cabecera { font-weight: bold; margin-bottom: 8px; }
  `]
})
export class TarjetaComponent implements AfterContentInit {
  @ContentChild('titulo') tituloElement!: ElementRef;

  ngAfterContentInit() {
    // El contenido proyectado ya está disponible
    console.log('Contenido proyectado inicializado');
    
    if (this.tituloElement) {
      console.log('Título encontrado:', this.tituloElement.nativeElement.textContent);
    }
  }
}

Uso del componente:

@Component({
  selector: 'app-ejemplo',
  template: `
    <app-tarjeta>
      <h3 #titulo slot="titulo">Mi Título</h3>
      <p>Este es el contenido de la tarjeta.</p>
    </app-tarjeta>
  `
})
export class EjemploComponent { }

ngAfterContentChecked - Verificación del contenido

El hook ngAfterContentChecked se ejecuta después de cada verificación del contenido proyectado. Es útil para reaccionar a cambios en el contenido que se proyecta desde el componente padre.

import { Component, AfterContentChecked, ContentChildren, QueryList, ElementRef } from '@angular/core';

@Component({
  selector: 'app-lista-pestañas',
  template: `
    <div class="pestañas">
      <ng-content select="app-pestaña"></ng-content>
      <p>Total de pestañas: {{ totalPestañas }}</p>
    </div>
  `
})
export class ListaPestañasComponent implements AfterContentChecked {
  @ContentChildren('pestaña') pestañas!: QueryList<ElementRef>;
  totalPestañas = 0;

  ngAfterContentChecked() {
    // Se ejecuta cada vez que se verifica el contenido proyectado
    const nuevaCantidad = this.pestañas?.length || 0;
    if (this.totalPestañas !== nuevaCantidad) {
      this.totalPestañas = nuevaCantidad;
      console.log(`Pestañas actualizadas: ${this.totalPestañas}`);
    }
  }
}

ngAfterViewInit - Vista inicializada

El hook ngAfterViewInit se ejecuta una vez después de que Angular haya inicializado completamente la vista del componente y todas sus vistas hijas. Este es el momento ideal para acceder a elementos del DOM o inicializar bibliotecas de terceros que requieren el DOM completo.

import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'app-grafico',
  template: `
    <div>
      <h3>Gráfico de Ventas</h3>
      <canvas #grafico width="400" height="200"></canvas>
      <p>{{ estadoGrafico }}</p>
    </div>
  `
})
export class GraficoComponent implements AfterViewInit {
  @ViewChild('grafico') canvas!: ElementRef<HTMLCanvasElement>;
  estadoGrafico = 'Cargando...';

  ngAfterViewInit() {
    // La vista ya está completamente inicializada
    this.inicializarGrafico();
  }

  private inicializarGrafico() {
    const ctx = this.canvas.nativeElement.getContext('2d');
    if (ctx) {
      // Dibujar un gráfico simple
      ctx.fillStyle = '#007bff';
      ctx.fillRect(50, 50, 100, 80);
      ctx.fillStyle = '#28a745';
      ctx.fillRect(200, 30, 100, 100);
      
      this.estadoGrafico = 'Gráfico cargado correctamente';
    }
  }
}

ngAfterViewChecked - Verificación de la vista

El hook ngAfterViewChecked se ejecuta después de cada verificación de la vista del componente y sus vistas hijas. Es útil para reaccionar a cambios en la vista después de que Angular haya actualizado el DOM.

import { Component, AfterViewChecked, ViewChildren, QueryList, ElementRef } from '@angular/core';

@Component({
  selector: 'app-galeria',
  template: `
    <div class="galeria">
      <h3>Galería de Imágenes</h3>
      @for (imagen of imagenes; track imagen.id) {
        <img #imagenRef [src]="imagen.url" [alt]="imagen.titulo">
      }
      <p>Imágenes cargadas: {{ imagenesCargadas }}</p>
    </div>
  `,
  styles: [`
    .galeria img { width: 100px; height: 100px; margin: 4px; }
  `]
})
export class GaleriaComponent implements AfterViewChecked {
  @ViewChildren('imagenRef') imagenesElementos!: QueryList<ElementRef>;
  
  imagenes = [
    { id: 1, url: 'imagen1.jpg', titulo: 'Imagen 1' },
    { id: 2, url: 'imagen2.jpg', titulo: 'Imagen 2' }
  ];
  
  imagenesCargadas = 0;

  ngAfterViewChecked() {
    // Contar imágenes que están en el DOM
    const cantidadActual = this.imagenesElementos?.length || 0;
    if (this.imagenesCargadas !== cantidadActual) {
      this.imagenesCargadas = cantidadActual;
    }
  }

  agregarImagen() {
    const nuevaId = this.imagenes.length + 1;
    this.imagenes.push({
      id: nuevaId,
      url: `imagen${nuevaId}.jpg`,
      titulo: `Imagen ${nuevaId}`
    });
  }
}

Orden de ejecución de los hooks

Es importante entender el orden en que se ejecutan estos hooks para usarlos correctamente:

import { Component, OnInit, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked } from '@angular/core';

@Component({
  selector: 'app-orden-hooks',
  template: `
    <div>
      <h3>Orden de Ejecución de Hooks</h3>
      <ng-content></ng-content>
      <p>Revisa la consola para ver el orden</p>
    </div>
  `
})
export class OrdenHooksComponent implements OnInit, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked {
  
  ngOnInit() {
    console.log('1. ngOnInit');
  }

  ngAfterContentInit() {
    console.log('2. ngAfterContentInit');
  }

  ngAfterContentChecked() {
    console.log('3. ngAfterContentChecked');
  }

  ngAfterViewInit() {
    console.log('4. ngAfterViewInit');
  }

  ngAfterViewChecked() {
    console.log('5. ngAfterViewChecked');
  }
}

Cuándo usar cada hook

  • ngAfterContentInit: Para configurar o acceder al contenido proyectado una sola vez
  • ngAfterContentChecked: Para reaccionar a cambios en el contenido proyectado (usar con precaución)
  • ngAfterViewInit: Para acceder al DOM, inicializar bibliotecas externas o configurar elementos de la vista
  • ngAfterViewChecked: Para reaccionar a cambios en la vista después de la detección de cambios

Los hooks de contenido y vista son fundamentales para trabajar con elementos del DOM y contenido proyectado, permitiéndonos ejecutar código en el momento exacto cuando estos elementos están disponibles y listos para ser manipulados.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Angular es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Angular

Explora más contenido relacionado con Angular y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

  • Comprender qué son los hooks de ciclo de vida en Angular y su importancia.
  • Aprender a usar los hooks de inicialización y cambios como ngOnInit, ngOnChanges y ngDoCheck.
  • Conocer los hooks relacionados con el contenido proyectado y la vista: ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit y ngAfterViewChecked.
  • Entender el orden de ejecución de los hooks y cuándo utilizar cada uno.
  • Aplicar buenas prácticas para optimizar el uso de los hooks y evitar problemas de rendimiento.