w3resource

Sharing Modules

It is not unusual to see a scenario where you need to create a component that is going to be used on different modules of your application.

Normally if you try to the component to multiple modules, angular is going to throw you an error:

Type xxxComponent is part of the declarations of 2 modules: xxxModule and yyyModule

It is in this situation that shared modules makes sense. Creating shared modules allows you to organize and streamline your code. You can put commonly used directives, pipes, and components into one module and then import just that module wherever you need it in other parts of your app.

Using components vs services from other modules.

There is an important distinction between using another module's component and using a service from another module. Import modules when you want to use directives, pipes, and components. Importing a module with services means that you will have a new instance of that service, which typically is not what you need (typically one wants to reuse an existing service). Use module imports to control service instantiation.

The most common way to get a hold of shared services is through Angular dependency injection, rather than through the module system (importing a module will result in a new service instance, which is not a typical usage).

How do we create shared modules?

First, off course, you need to create a Module. It doesn’t need to include the word shared anywhere, it can be just something like:

TypeScript Code:

import{NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
   imports:[
     CommonModule
   ]
})
export class DateModule{}

Live Demo:

It is just a code snippet explaining a particular concept and may not have any output

See the Pen sharedModule0.ts by w3resource (@w3resource) on CodePen.


This module is going to contain everything related with dates for your application (date-picker, formatters and so on...).

Let's now include a component into this Module...

TypeScript Code:

import {DatePickerComponent} from './datepicker.component';

import{NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
   imports:[
     CommonModule
   ],
declarations:[
	DatePickerComponent
]
})
export class DateModule{}

Live Demo:

It is just a code snippet explaining a particular concept and may not have any output

See the Pen sharedModule1.ts by w3resource (@w3resource) on CodePen.


So far everything is just like if you are creating a regular module, but this is not enough, you need to make the DatePickerComponent accessible for other modules using this module. For that you need to add the datepicker component to the module exports array:

TypeScript Code:

import {DatePickerComponent} from './datepicker.component';

import{NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
   imports:[
     CommonModule
   ],
declarations:[
	DatePickerComponent
],
exports: [
 DatePickerComponent
  ]
})
export class DateModule{}

Live Demo:

It is just a code snippet explaining a particular concept and may not have any output

See the Pen sharedModule2.ts by w3resource (@w3resource) on CodePen.


Now you are allowing others modules that import DateModule to have access to DatePickerComponent.

Using this same approach you can export pipes and directives but you can't use this to export services. For services you need to add the function forRoot() to the shared Module. You are going to end up with something like this:

TypeScript Code:

import {DatePickerComponent} from './datepicker.component';
import{NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
   imports:[
     CommonModule
   ],
declarations:[
	DatePickerComponent
],
exports: [
 DatePickerComponent
  ]
})
export class DateModule{
static forRoot(){
return {
ngModule:DateModule,
providers: [DateFormatterService]
};
}
}

Live Demo:

It is just a code snippet explaining a particular concept and may not have any output

See the Pen sharedModule3.ts by w3resource (@w3resource) on CodePen.


By convention, the forRoot static method both provides and configures services at the same time. In the case of this kind of shared Modules (that's expose services), you need to add them and call the forRoot in your root module (AppModule usually) to be certain of having a global instance of the exposed services.

You can also pass a params to the forRoot method to configure the service initialization. If you need params your code is going to end up something like:

TypeScript Code:

import {DatePickerComponent} from './datepicker.component';
import{NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
   imports:[
     CommonModule
   ],
declarations:[
	DatePickerComponent
],
exports: [
 DatePickerComponent
  ]
})
export class DateModule{
static forRoot(){
return {
ngModule:DateModule,
providers: [
{provide: DateFormatterService, useValue:culture
}]
};
}
}

Live Demo:

It is just a code snippet explaining a particular concept and may not have any output

See the Pen sharedModule4.ts by w3resource (@w3resource) on CodePen.


In your service you receive this values on the constructor:

import {Injectable, Optional} from '@angular/core';
@Injectable()
Export class DataFormatterService {
Constructor(@optional() private _culture:String){}
}

Conclusion

Creating shared modules in angular is quite simple and you are going to need to create one sooner or later in your app. Even if at first it may sound kind of scary, you are going to feel confortable working with them and all their advantages.

Previous: NgModule API
Next: NgModule FAQs



Follow us on Facebook and Twitter for latest update.