Monday, September 5, 2016

Appendix 1 - Modules

Modules

Once app grows, maintenance becomes more importantt and challenging. Better to divide a large app into smaller parts - Each focusing on one specific functionality.  In each part, we have a group of classes that are highly related and they work together to fulfil a goal.

like facebook, different funcitonalities, messaging, games, news feed, we have classes highly related yet are different frmo other parts. We call each area a module, component, package.

Module: a block of highly related classes.

Ecah app has at least one module AppModule.

When it grows, can refactor:

AppModule
- Module, users
- Module, posts
- Module

In each class, add a decorator called NgModule

// provide metadata to angular about this module
@NgModule({
  imports: [...], // dependencies of this module
  declarations: [...], //which classes are part of this module, components, directives, types
  exports: [...], // which classes are available to outside modules
  providers: [...] // providers for dependency injection
})
export class UsersModule{
}

Need Seed Project (RC5)

Changes:
new file app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';
import { HomeComponent } from './home.component';
import { NotFoundComponent } from './not-found.component';

import { MessagesModule } from './messages/messages.module'; 
import { PhotosModule } from './photos/photos.module';

import {routing} from './app.routing';

@NgModule({
  imports: [
    BrowserModule,
    MessagesModule,
    PhotosModule,
    routing
  ],
  declarations: [ 
    AppComponent,
    HomeComponent,
    NotFoundComponent
  ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

main.ts

purely boilerplate food. Doesn't change angular concepts that we have learned.

Working with Modules

old way of implementation

app.component.ts

import {MessagesComponent} from './messages.component';

@Component({
  selector: 'my-app',
  template: '<messages></messages>',
  directives: [ MessagesComponent]
})
export class AppComponent {}


Problem was that we have to always call in directives, MessagesComponent. With modules, we register messages component at module level, and it will be available to components in this module.

app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';

import { AppComponent }  from './app.component';

import { MessagesModule } from './messages/messages.module'; 
import { MessagesServices } from './messages/messages.service'; 

import {routing} from './app.routing';

@NgModule({
  imports: [
    BrowserModule, 
    FormsModule
  ],
  declarations: [ 
    AppComponent,
    MessagesComponent
  ],
  providers: [MessagesService],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

app.component.ts

import {MessagesComponent} from './messages.component';

@Component({
  selector: 'my-app',
  template: '<messages></messages>',
  directives: [ MessagesComponent],
  providers: [ MessagesService ]
})
export class AppComponent {}

messages.component.ts

import { Component } from '@angular/core';
import { MessagesService } from './messages.service';

@Component({
    selector: 'messages',
    template: `<h1>Messages</h1>
    <input [(ngModel)]="title">
    <ul>
        <li *ngFor="let m of messages">{{ m }}</li>
    </ul>
    `
})
export class MessagesComponent {
    messages;

    title = "New Message"

    constructor(service : MessagesService) {
        this.messages = service.getMessages();

    }

}

Extracting Modules continue from #158

add new folder 'messages'. add new file 'messages.module.ts'

import { NgModule } from '@angular/code';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

import { MessagesComponent } from './messages/messages.component'; 

import { MessagesServices } from './messages/messages.service'; 

@NgModule({
  imports: [
    FormsModule,
    CommonModule
  ],
  declarations: [
    MessagesComponent
  ],
  exports: [
    MessagesComponent // only export elements used in template <messages></messages>
  ],
  providers: [
    MessagesService
  ]
  
})
export class MessagesModule{
}

app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { MessagesModule } from './messages/messages.module'; 

import { AppComponent }  from './app.component';

import { MessagesComponent } from './messages/messages.component'; 
import { MessagesServices } from './messages/messages.service'; 

import {routing} from './app.routing';

@NgModule({
  imports: [
    BrowserModule, 
    FormsModule
    MessagesModule
  ],
  declarations: [ 
    AppComponent
    MessagesComponent
  ],
  providers: [MessagesService],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

After refactoring, notice how our app.module becomes smaller? And it only changes when we add new modules to this app. So messages module can grow on its own, we can add to it, new classes, new components, new pipes, new directives and non of this impact our app.module. This is the benefit of modularity.

messages.component.ts

import { Component } from '@angular/core';
import { MessagesService } from './messages.service';

@Component({
    selector: 'messages',
    template: `<h1>Messages</h1>
    <input [(ngModel)]="title">
    <ul>
        <li *ngFor="let m of messages">{{ m }}</li>
    </ul>
    `
})
export class MessagesComponent {
    messages;

    title = "New Message"

    constructor(service : MessagesService) {
        this.messages = service.getMessages();

    }

}

No comments:

Post a Comment