[Latest News][6]

Angular 5

Angular 5 : Module and Feature Modules


Important announcement : We are moving all our content to new website - Witscad Courses . You can find the updated complete Angular course here - A Complete Angular Tutorial. Feel free to visit.

Angular modules are designed to distribute our application into blocks of different modules which are more manageable. As our application starts growing incorporating more features and functionalities, it becomes tedious to manages if we keep on adding code into our single block of application. Then there comes a time when we have to code our new big features into a different module. We then use that module in our main application module.

Angular modules are independent block of distributable code. These can be exported as a library. For e.g. Angular provides us with BrowserModule, HttpModule, FormsModule etc. Similarly we can make our own Angular module which can be used in one or more application depending on the scope of functionality which we are building,

It is much easier to do with Angular Modules.

An Angular Module is a class with ngModule decorator.

Features of and Angular module

It declares its own set of Components, Directives and Pipes.
It can be exported as an angular module where other modules con consume its components, directives and pipes.
It provide services to itself and other modules.
It can import other modules in its own module declaration and use their components, directives and pipes.

If we look at our default app.module.ts file, we will find something similar code like this:
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

export class App { 
  constructor() {
  
  }
}

NgModule({
  imports: [ BrowserModule ],
  declarations: [ App],
  providers : [],
  bootstrap: [ App ]
})
export class AppModule {}
The @ngModule() directive have some different sets of settings. Let's look at them one by one.

imports

This is an array where we define other modules that we want to import in our main application module such as BrowserModule, FormsModule or any other third party module. One thing to note that when we export our module, all other modules that we imported are also available in our exported module. If A import B and C imports A, this means C does not have access to B.

declaration

This is an array which defines all the components, directives, pipes that belong to our angular module. Each of them must belong to only one angular module.

bootstrap

This is used to load the application module in Angular ecosystem. The application must bootstrap at least one component which is the root application component. It should only be used in the root application module.

exports

This is an array that is used to export components, directives and pipes to other module.

providers

This is an array where we define services of our module. This can be either at root level or any component level. If we have defined our service in providers array at root level, then that service will also be available to all child components. If we want a service available to a particular component only then we define that service to that component's provider array only.

Feature Module

A Feature Module in Angular is a module other than our main application root module that is decorated by @ngModule() decorator and hence share the same property configurations like application root module. You can also say it a custom module or an external module, but Feature Module is an Angular way of saying wherein we separate our features of our main application into a different module.

As our application starts growing bigger, it's better to re-factor at early stage so that the application stays manageable. Implementing Feature modules is a way of re-factoring our application.

Example application - Mail Client

Ok, so now we will move on to building an example application which is Mail Client. We will introduce two Feature modules - Mail Box and Address Book in our main application root module i.e. Mail Client.

MailClient component

Here we are just showing the version of the mail client which we input from main application component.
import {Component, Input} from '@angular/core'

@Component({
  selector: 'mail-client',
  template: `
    <div>
      <h2>MailClient : v - {{version}} </h2>
    </div>
  `
})
export class MailClient {
  @Input() version:number;
  constructor(){
   
  }

}

MailBox Feature module

This is our MailBox Feature Module which have a MailBox component and a MailBox service
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MailBoxComponent } from './mailBox.component'
import { MailBoxService } from './mailBox.service'

@NgModule({
  imports:      [ CommonModule ],
  declarations: [ MailBoxComponent ],
  exports:      [ MailBoxComponent ],
  providers:    [ MailBoxService ]
})
export class MailBoxModule { }

MailBox Service

It contains one method which provides inbox mails (values hard-codes for demo, can be extended).
import {Injectable} from '@angular/core'

@Injectable()
export class MailBoxService {
  constructor(){
    
  }
  
  getInboxMails():string[] {
    return [
      "Welcome to MailClient",
      "Daily Newsletter",
      "20% discount on this product"
      ];
  }
}

MailBox component

It displays all the mails provided by the MailBox Service.
import { Component } from '@angular/core'
import { MailBoxService } from './mailBox.service'

@Component({
  selector: 'mail-box',
  template: `
    <div>
      <h2>Mail Box</h2>
      <div ngFor='let ibMail of inboxMails; let idx = index'>
        <div>{{idx+1}} - {{ibMail}}</div>
      </div>
    </div>
  `
})
export class MailBoxComponent implements OnInit{
  inboxMails:string[];
  constructor(private _service: MailBoxService){
   
  }
  
  ngOnInit(){
    this.inboxMails = this._service.getInboxMails();
  }
}


AddressBook Module

In the similar way, we will create another Feature module - Address Book Feature Module. This will have the AddressBook component and an AddressBook service.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AddressBookComponent } from './addressBook.component'
import { AddressBookService } from './addressBook.service'

@NgModule({
  imports:      [ CommonModule ],
  declarations: [ AddressBookComponent ],
  exports:      [ AddressBookComponent ],
  providers:    [ AddressBookService ]
})
export class AddressBookModule { }

AddressBookService

import {Injectable} from '@angular/core'

@Injectable()
export class AddressBookService {
  constructor(){
    
  }
  
  getContacts():string[] {
    return [
      "Alice ([email protected])",
      "Bob ([email protected])",
      "Chris ([email protected])"
      ];
  }
}

AddressBookComponent


import { Component } from '@angular/core'
import { AddressBookService } from './addressBook.service'

@Component({
  selector: 'address-book',
  template: `
    <div>
      <h2>Address Book</h2>
      <div ngFor='let contact of contacts; let idx = index'>
        <div>{{idx+1}} - {{contact}}</div>
      </div>
    </div>
  `
})
export class AddressBookComponent implements OnInit{
  contacts : string[];
  constructor(private _service : AddressBookService){
   
  }
  
  ngOnInit(){
    this.contacts = this._service.getContacts();
  }
}
Note : Both in the MailBoxModule and AddressBookModule, we are not importing BrowserModule but we are importing CommonModule. The reason is that some essential services to launch and run a browser app is provided by BrowserModule. BrowserModule also re-exports CommonModule from @angular/common. We should not import BrowserModule in any other module. Feature modules and lazy-loaded modules should import CommonModule instead.

Full source code is here

https://embed.plnkr.co/jfhvoV/

2 comments

  1. Nice tutorial!

    I wonder if I could generate a bundle with the feature module in order to be imported into another app.

    I am googling but I have only found a tutorial but it doesn't explain how to correctly export a feature module.

    Would you mind to publish an example for doing it?

    Thanks in advance!

    Best regards.

    ReplyDelete
  2. Following with my last comment, I have built an application which imports several modules that by themselves are applications more complex.

    Your solution integrates several feature modules into the backbone of an application because these modules are enough small to be integrated easier but in my case would be unstable in the long-term.

    I am still googling about how to import big feature modules into another main app. :)

    Anyway, let me know how to do it.

    ReplyDelete

Comment Here

Start typing and press Enter to search