Introducción

En Angular, la inyección de dependencias (DI) es una técnica poderosa que permite a los desarrolladores gestionar las dependencias de sus aplicaciones de manera eficiente. Los inyectores jerárquicos son una característica avanzada de Angular que permite una mayor flexibilidad y control sobre cómo se resuelven las dependencias en diferentes niveles de la aplicación.

Conceptos Clave

  1. Inyectores: Un inyector es un contenedor que mantiene un registro de los proveedores y sus dependencias. Cuando se necesita una dependencia, el inyector la proporciona.
  2. Jerarquía de Inyectores: Angular crea una jerarquía de inyectores que permite que los servicios sean compartidos o aislados en diferentes niveles de la aplicación.
  3. Proveedores: Los proveedores son responsables de crear instancias de servicios que pueden ser inyectados en componentes, directivas, y otros servicios.

Jerarquía de Inyectores en Angular

Angular crea una jerarquía de inyectores que se organiza en niveles. Los niveles principales son:

  1. Inyector Raíz: Es el inyector global que se crea cuando se inicia la aplicación Angular. Los servicios proporcionados en el inyector raíz están disponibles en toda la aplicación.
  2. Inyectores de Módulo: Cada módulo puede tener su propio inyector. Los servicios proporcionados en un módulo están disponibles solo dentro de ese módulo y sus descendientes.
  3. Inyectores de Componente: Cada componente puede tener su propio inyector. Los servicios proporcionados en un componente están disponibles solo dentro de ese componente y sus descendientes.

Ejemplo Práctico

Paso 1: Crear un Servicio

Primero, crearemos un servicio llamado LoggingService que se utilizará para demostrar la jerarquía de inyectores.

// logging.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root' // Proporcionado en el inyector raíz
})
export class LoggingService {
  log(message: string) {
    console.log(message);
  }
}

Paso 2: Crear un Módulo y un Componente

A continuación, crearemos un módulo y un componente para demostrar cómo funcionan los inyectores jerárquicos.

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ChildComponent } from './child/child.component';
import { LoggingService } from './logging.service';

@NgModule({
  declarations: [
    AppComponent,
    ChildComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
// child.component.ts
import { Component, OnInit } from '@angular/core';
import { LoggingService } from '../logging.service';

@Component({
  selector: 'app-child',
  template: `<p>Child Component</p>`,
  providers: [LoggingService] // Proporcionado en el inyector del componente
})
export class ChildComponent implements OnInit {
  constructor(private loggingService: LoggingService) { }

  ngOnInit(): void {
    this.loggingService.log('Child Component Initialized');
  }
}

Paso 3: Probar la Jerarquía de Inyectores

En este ejemplo, LoggingService se proporciona en dos niveles diferentes: el inyector raíz y el inyector del componente ChildComponent. Esto significa que:

  • Cuando LoggingService se inyecta en AppComponent, se utiliza la instancia proporcionada por el inyector raíz.
  • Cuando LoggingService se inyecta en ChildComponent, se utiliza una nueva instancia proporcionada por el inyector del componente.
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { LoggingService } from './logging.service';

@Component({
  selector: 'app-root',
  template: `<app-child></app-child>`,
})
export class AppComponent implements OnInit {
  constructor(private loggingService: LoggingService) { }

  ngOnInit(): void {
    this.loggingService.log('App Component Initialized');
  }
}

Ejercicio Práctico

Ejercicio

  1. Crea un nuevo servicio llamado DataService que tenga un método getData que retorne un arreglo de datos.
  2. Proporciona DataService en el inyector raíz.
  3. Crea un nuevo componente llamado ParentComponent y proporciona DataService en el inyector del componente.
  4. Inyecta DataService en ParentComponent y en un componente hijo llamado ChildComponent.
  5. Observa cómo se comporta DataService en ambos componentes.

Solución

// data.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  getData() {
    return ['Data 1', 'Data 2', 'Data 3'];
  }
}
// parent.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-parent',
  template: `<app-child></app-child>`,
  providers: [DataService]
})
export class ParentComponent implements OnInit {
  constructor(private dataService: DataService) { }

  ngOnInit(): void {
    console.log(this.dataService.getData());
  }
}
// child.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-child',
  template: `<p>Child Component</p>`
})
export class ChildComponent implements OnInit {
  constructor(private dataService: DataService) { }

  ngOnInit(): void {
    console.log(this.dataService.getData());
  }
}

Conclusión

Los inyectores jerárquicos en Angular proporcionan una forma flexible y poderosa de gestionar dependencias en diferentes niveles de la aplicación. Al comprender cómo funcionan los inyectores jerárquicos, puedes controlar mejor el alcance y la reutilización de los servicios en tu aplicación Angular.

Curso de Angular 2+

Módulo 1: Introducción a Angular

Módulo 2: Conceptos Básicos de TypeScript

Módulo 3: Componentes y Plantillas

Módulo 4: Directivas y Pipes

Módulo 5: Servicios e Inyección de Dependencias

Módulo 6: Enrutamiento y Navegación

Módulo 7: Formularios en Angular

Módulo 8: Cliente HTTP y Observables

Módulo 9: Gestión de Estado

Módulo 10: Pruebas en Angular

Módulo 11: Temas Avanzados

Módulo 12: Despliegue y Mejores Prácticas

© Copyright 2024. Todos los derechos reservados