You are here:  Freelancer Tips  »  Article

 
17.05.2018

Usando forRoot() y forChild() para configurar módulos en Angular


Los módulos en Angular son bastante complejos y muchas veces cuesta entenderlos. Aunque la documentación preparada por Angular sea detallada, sus múltiples ámbitos la hacen compleja. Sebastián Puentes, ingeniero en informática, nos detalla en este artículo como inyectar configuraciones con forRoot() y forChild() en Angular.


Esencialmente, forRoot y forChild nos permiten tener control de los providers (nuestros injectables) dependiendo del tipo de carga que queramos darle. Esto puede permitirnos tener diferentes configuraciones para distintos casos de la carga.

 

¿Cuándo se usa forRoot en Angular?

 

Se usa forRoot cuando un módulo es “eager”, esto es, no es lazy-loaded (lo cargamos al iniciar la aplicación). Angular crea un factory para todos los módulos, excepto los módulos lazy, que al cargarse bajo demanda, tienen su propio factory. Cuando nosotros usamos forRoot(), lo que estamos haciendo es cargar un provider que va a ser inyectado hacia la “raíz” de los módulos gracias a que usa el mismo factory que nuestro módulo principal.

En términos simples, esto significa que usar forRoot nos permite acceder a nuestros providers desde cualquier punto de la aplicación que no sea lazy loaded. Entonces, si nosotros implementamos un ejemplo como:

export class ExampleModule{

 static forRoot(): ModuleWithProviders {

 return {

   ngModule: ExampleModule,

   providers:[

     {

       provide: MyService,

       useClass: MyEagerService

     }

   ]

 };

} }

Lo que estamos haciendo es decir que ese módulo, y los providers, va a cargarse “globalmente” para la app. En este caso, “MyService” sera la clase “MyEagerService” para cualquier modulo que no sea lazy-loaded de nuestra app.

 

¿Cuándo se usa forChild en Angular?

 

Se usa forChild al reves: cuando queremos entregar un provider que es visible solamente para los módulos “hijos” de nuestro modulo, en el caso de que sean lazy loaded. Como cada modulo lazy se carga bajo demanda, tiene su propio inyector.

Siguiendo con el ejemplo de arriba, podemos decir:

export class ExampleModule {

 static forChild(): ModuleWithProviders {

 return {

   ngModule: ExampleModule,

   providers:[

     {

       provide: MyService,

       useClass: MyLazyService

     }

   ]

 };

} }

En este caso, estamos diciendo que cuando el módulo sea lazy-loaded, nuestro provider “MyService” va a ser la clase MyLazyService.

Podemos incluso definir no solo distintas clases para un mismo provider usando forRoot() y forChild(), si no que incluso, distintos providers dependiendo de como lo instanciamos.

export class ExampleModule {

 static forRoot(): ModuleWithProviders {

 return {

   ngModule: AModule,

   providers:[MyService]

 };

static forChild(): ModuleWithProviders {

 return {

   ngModule: AModule,

   providers:[MyLazyService]

 };

} }

Aca tenemos un mismo modulo que cargará dos providers distintos dependiendo si es llamado como “forRoot”, o “forChild”.

 

¡Únete a nuestra comunidad de expertos IT! Crea tu perfil como desarrollador en pocos minutos.

✔ Aplica ilimitadamente ✔ Gana proyectos ✔ Paga 0 comisiones.  

Regístrate gratis

forRoot y forChild para inyectar configuraciones a módulos

 

Más allá de la utilidad de controlar que instanciamos al importar nuestros módulos, forRoot y forChild nos ofrecen algo mucho más útil: Poder inyectar configuraciones a nuestros módulos.

export interface CoreModuleConfig {

 environment: string;

}

 

 

export class ExampleModule {

 static forRoot(conf: ModuleConfig): ModuleWithProviders {

 return {

   ngModule: AModule,

   providers:[{provide:CONFIG, useClass: conf}]

 };

} }

Aquí, he definido una interfaz llamada ModuleConfig con un parámetro para mi modulo (environment). Esta interfaz se entrega como parametro al metodo forRoot(), el que toma ese objeto entrante definiéndolo como el provider CONFIG.

¿Qué quiere decir esto? Que al usar forRoot, el valor del provider CONFIG será el que entregaremos como parametro a forRoot cuando lo llamemos.

En términos simples, al importar ExampleModule entregandole el objeto a forRoot, como en este ejemplo...

@NgModule({

 declarations: [

   AppComponent,

      ...

 ],

 imports: [

   ExampleModule.forRoot({

     environment: “testing”

  }),

...estamos diciéndole a ExampleModule que use los valores definidos como parámetros como su provider de nombre CONFIG. Si llamamos a CONFIG.environment, su valor será “testing”.

forChild podemos usarlo de la misma forma, sin embargo, lo usaremos cuando queramos configurar un módulo lazy loaded.

Esto es especialmente util para configurar módulos que después serán exportados de forma independiente, por ejemplo.

 

Una advertencia sobre usar lógica en los métodos forRoot y forChild

 

Los métodos forRoot y forChild, si bien son funciones,es recomendable que solo tengan “return”, sin implementar más lógica. Esto, debido a que por defecto angular compila las aplicaciones de producción, usando la compilación AoT (Ahead of Time). Lamentablemente, si bien la logica que implementemos dentro de forRoot antes del return funcionara en una compilación JiT, en AoT arrojará el siguiente error:

Error: Error encountered resolving symbol values statically. Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function

Este código, por ejemplo, no funcionará en AoT.

function init(){

 console.log(“hola!”);

}

 

export class ExampleModule {

 static forRoot(): ModuleWithProviders {

      init();

 return {

   ngModule: AModule,

   providers:[MyService]

 };

Pero como solución, podemos usar un inicializador enganchandose al inicializador de Angular. Podemos definir un provider con el tag APP_INITIALIZER, y la función que le entreguemos, se iniciará cuando parta nuestra app, siempre que nuestra función sea una función exportada.

export function init(){

 console.log(“hola!”);

}

 

export class ExampleModule {

 static forRoot(): ModuleWithProviders {

      init();

 return {

   ngModule: AModule,

   providers:[MyService, {provide:APP_INITIALIZER,useClass:init]

 };

Este código si podrá compilar en AoT, y el método init() se ejecutará al cargar nuestra aplicación.

Esos son algunos usos interesantes para los metodos forRoot y forChild de los modulos Angular. Bien usados, pueden ser un gran apoyo en crear aplicaciones simples, limpias y escalables.

Crea tu perfil freelance gratis y consigue proyectos ¡sin comisiones!

 ¡Regístrate ahora!

More articles

  • Cómo organizar ‘Meetups’ en 7 pasos e impulsar tu carrera freelance

    Hoy en día, son muchos quienes optan por Internet cuando se trata de crear redes o para intereses específicos. Pero ya no tienes que reunirte de manera virtual gracias a Meetup. Si no has oído hablar de este servicio antes, este artículo te interesa.
  • 7 preguntas frecuentes en una entrevista a un diseñador web y cómo contestarlas

    Las entrevistas de trabajo pueden representar un reto considerable para los diseñadores de páginas web freelance. Algunas veces tu entrevistador no sabrá ni lo más elemental en lo que respecta al diseño web y otras será un experto en la materia. Así que nunca sabes lo que te vas a encontrar.
  • Comenzar un negocio de impresión en 3D: 5 cosas que debes saber

    La impresión en 3D está en alza de un tiempo a esta parte. No solo la tecnología ha mejorado mucho en los últimos cinco años, sino que también resulta más accesible desde el punto de vista económico. La impresión a partir de piezas de plástico y otros materiales puede sonar como un entretenimiento para tu tiempo libre, y, de hecho, lo es. Pero también puede ser la base de un negocio.

Comments

  • No comments available

Comment this article