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 y proporcionan las dependencias en diferentes niveles de la aplicación.
Conceptos Clave
- Inyectores: Son responsables de crear instancias de dependencias y proporcionarlas a las clases que las necesitan.
- Jerarquía de Inyectores: Angular permite definir inyectores en diferentes niveles de la aplicación, creando una jerarquía. Esto significa que los inyectores pueden estar anidados y cada uno puede tener su propio conjunto de proveedores.
- Proveedores: Son objetos que indican al inyector cómo crear una instancia de una dependencia.
Jerarquía de Inyectores en Angular
En Angular, los inyectores pueden estar definidos en diferentes niveles:
- Inyector Raíz: Es el inyector global que se crea cuando se inicia la aplicación Angular. Proporciona dependencias a toda la aplicación.
- Inyectores de Módulo: Cada módulo puede tener su propio inyector, que puede proporcionar dependencias específicas a ese módulo.
- Inyectores de Componente: Cada componente puede tener su propio inyector, que puede proporcionar dependencias específicas a ese componente y sus hijos.
Ejemplo de Jerarquía de Inyectores
Consideremos una aplicación Angular con la siguiente estructura:
- AppModule
- FeatureModule
- FeatureComponent
- ChildComponent
- FeatureModule
En este caso, la jerarquía de inyectores sería:
- Inyector Raíz: Proporciona dependencias a toda la aplicación.
- Inyector de FeatureModule: Proporciona dependencias específicas a
FeatureModule. - Inyector de FeatureComponent: Proporciona dependencias específicas a
FeatureComponenty sus hijos, comoChildComponent.
Configuración de Inyectores Jerárquicos
Proveedores en el Inyector Raíz
Para definir un proveedor en el inyector raíz, se utiliza el decorador @Injectable con la propiedad providedIn: 'root':
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class RootService {
constructor() { }
}Proveedores en el Inyector de Módulo
Para definir un proveedor en el inyector de un módulo, se utiliza la propiedad providers en el decorador @NgModule:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FeatureComponent } from './feature.component';
import { FeatureService } from './feature.service';
@NgModule({
declarations: [FeatureComponent],
imports: [CommonModule],
providers: [FeatureService]
})
export class FeatureModule { }Proveedores en el Inyector de Componente
Para definir un proveedor en el inyector de un componente, se utiliza la propiedad providers en el decorador @Component:
import { Component } from '@angular/core';
import { ComponentService } from './component.service';
@Component({
selector: 'app-feature',
templateUrl: './feature.component.html',
styleUrls: ['./feature.component.css'],
providers: [ComponentService]
})
export class FeatureComponent {
constructor(private componentService: ComponentService) { }
}Ejemplo Práctico
Vamos a crear un ejemplo práctico para ilustrar cómo funcionan los inyectores jerárquicos en Angular.
Paso 1: Crear Servicios
Primero, creamos tres servicios: RootService, FeatureService y ComponentService.
// root.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class RootService {
getMessage() {
return 'Mensaje del RootService';
}
}
// feature.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class FeatureService {
getMessage() {
return 'Mensaje del FeatureService';
}
}
// component.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class ComponentService {
getMessage() {
return 'Mensaje del ComponentService';
}
}Paso 2: Configurar Módulo y Componente
Luego, configuramos el módulo y el componente para utilizar estos servicios.
// feature.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FeatureComponent } from './feature.component';
import { FeatureService } from './feature.service';
@NgModule({
declarations: [FeatureComponent],
imports: [CommonModule],
providers: [FeatureService]
})
export class FeatureModule { }
// feature.component.ts
import { Component } from '@angular/core';
import { RootService } from '../root.service';
import { FeatureService } from './feature.service';
import { ComponentService } from './component.service';
@Component({
selector: 'app-feature',
templateUrl: './feature.component.html',
styleUrls: ['./feature.component.css'],
providers: [ComponentService]
})
export class FeatureComponent {
constructor(
private rootService: RootService,
private featureService: FeatureService,
private componentService: ComponentService
) { }
getMessages() {
console.log(this.rootService.getMessage());
console.log(this.featureService.getMessage());
console.log(this.componentService.getMessage());
}
}Paso 3: Utilizar el Componente
Finalmente, utilizamos el componente en nuestra aplicación y llamamos al método getMessages para ver los mensajes de los diferentes servicios.
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angular-hierarchical-injectors';
}Ejercicio Práctico
Ejercicio
- Crea un nuevo servicio llamado
ChildServicey configúralo para que sea proporcionado en el inyector del componenteChildComponent. - Modifica
ChildComponentpara inyectar y utilizarChildService. - Asegúrate de que
ChildComponentimprima un mensaje desdeChildServicecuando se inicialice.
Solución
// child.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class ChildService {
getMessage() {
return 'Mensaje del ChildService';
}
}
// child.component.ts
import { Component, OnInit } from '@angular/core';
import { ChildService } from './child.service';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css'],
providers: [ChildService]
})
export class ChildComponent implements OnInit {
constructor(private childService: ChildService) { }
ngOnInit() {
console.log(this.childService.getMessage());
}
}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 y cómo configurarlos, puedes crear aplicaciones más modulares y mantenibles. En el siguiente módulo, exploraremos cómo configurar rutas y navegar entre diferentes vistas en una aplicación Angular.
Curso de Angular
Módulo 1: Introducción a Angular
- ¿Qué es Angular?
- Configuración del Entorno de Desarrollo
- Arquitectura de Angular
- Primera Aplicación Angular
Módulo 2: Componentes de Angular
- Entendiendo los Componentes
- Creación de Componentes
- Plantillas de Componentes
- Estilos de Componentes
- Interacción entre Componentes
Módulo 3: Enlace de Datos y Directivas
- Interpolación y Enlace de Propiedades
- Enlace de Eventos
- Enlace de Datos Bidireccional
- Directivas Incorporadas
- Directivas Personalizadas
Módulo 4: Servicios e Inyección de Dependencias
- Introducción a los Servicios
- Creación y Uso de Servicios
- Inyección de Dependencias
- Inyectores Jerárquicos
Módulo 5: Enrutamiento y Navegación
Módulo 6: Formularios en Angular
- Formularios Basados en Plantillas
- Formularios Reactivos
- Validación de Formularios
- Formularios Dinámicos
Módulo 7: Cliente HTTP y Observables
- Introducción al Cliente HTTP
- Realizando Solicitudes HTTP
- Manejo de Respuestas HTTP
- Uso de Observables
- Manejo de Errores
Módulo 8: Gestión de Estado
- Introducción a la Gestión de Estado
- Uso de Servicios para la Gestión de Estado
- NgRx Store
- NgRx Effects
- NgRx Entity
Módulo 9: Pruebas en Angular
- Pruebas Unitarias
- Pruebas de Componentes
- Pruebas de Servicios
- Pruebas de Extremo a Extremo
- Simulación de Dependencias
Módulo 10: Conceptos Avanzados de Angular
- Angular Universal
- Optimización del Rendimiento
- Internacionalización (i18n)
- Pipes Personalizados
- Animaciones en Angular
