NgModule dan Optimization – 2

Pada bab ini kita akan membahas pemisahan Angular module berdasarkan fitur. Sebagai gambaran sederhana lihat gambar dibawah.

Perhatian pemisahan fitur tidak berarti terdapat module khusus, tetap menggunakan NgModule, hanya dipisahkan dalam file terpisah berdasarkan fitur. Bila melihat gambar dibawah, maka akan dipisahkan dalam fitur Products dan Orders

Mari kita implementasikan ide diatas dalam project buku resep yang sudah “selesai” kita develop.

Jika kita perhatikan directory dari file yang kita buat, terdapat 3 fitur utama, yaitu auth, recipe dan shopping list.

Sementara untuk Header adalah bagian dari app component, sementara shared, sesuai namanya adalah component yang dapat digunakan oleh fitur-fitur diatas.

Memisahkan Component Berdasarkan Fitur

Sebagai contoh, kita gunakan fitur recipes. Buka folder recipes, lalu buat file recipes.module.ts, pindahkan declrations yang berhubungan dengan recipes dari app.module.ts

Perhatian, perlu melakukan import module yang digunakan oleh module dalam array declarations. Contoh, component RecipeEditComponent memerlukan Form Module, maka perlu ditambahkan pada property key imports.

import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { CommonModule } from "@angular/common";
import { ReactiveFormsModule } from "@angular/forms";

import { RecipesComponent } from './recipes.component';
import { RecipeListComponent } from './recipe-list/recipe-list.component';
import { RecipeDetailComponent } from './recipe-detail/recipe-detail.component';
import { RecipeItemComponent } from './recipe-list/recipe-item/recipe-item.component';
import { RecipeHomeComponent } from './recipe-home/recipe-home.component';
import { RecipeEditComponent } from './recipe-edit/recipe-edit.component';



@NgModule({
    declarations: [
        RecipesComponent,
        RecipeListComponent,
        RecipeDetailComponent,
        RecipeItemComponent,
        RecipeHomeComponent,
        RecipeEditComponent,
    ],
    imports:[
        CommonModule,
        ReactiveFormsModule,
        RouterModule
    ],

    exports:[
        RecipesComponent,
        RecipeListComponent,
        RecipeDetailComponent,
        RecipeItemComponent,
        RecipeHomeComponent,
        RecipeEditComponent,
    ]
})
export class RecipesModule {}

Kemudian pada app.module.ts, kita import recipes.module.ts

import { NgModule} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule, ReactiveFormsModule } from '@angular/forms';
import {HttpClientModule} from '@angular/common/http';

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

import { ShoppingListComponent } from './shopping-list/shopping-list.component';
import { ShoppingEditComponent } from './shopping-list/shopping-edit/shopping-edit.component';
import { DropDownDirective } from './shared/dropdown.directive';
import { ShoppingListService } from './shopping-list/shopping-list.service';
import { AppRoutingModule } from './app-routing.module';

import { RecipeService } from './recipes/recipe.service';
import { AuthComponent } from './auth/auth.component'; 
import { LoadingSpinnerComponent } from './shared/loading-spinner/loading-spinner.component';
import { AlertComponent } from './shared/alert/alert.component';
import { PlaceholderDirective } from './shared/placeholder/placeholder.directive';

//import RecipesModule  jika IDE tidak otomatis
import { RecipesModule } from './recipes/recipes.module';

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    
    ShoppingListComponent,
    ShoppingEditComponent,
    DropDownDirective,

    AuthComponent,
    LoadingSpinnerComponent,
    AlertComponent,
    PlaceholderDirective 
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    AppRoutingModule,
    RecipesModule //import recipe module
  ],
  providers: [ShoppingListService, RecipeService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Dapat dilihat, sekarang app.module.ts, lebih ringkas. Dan code juga lebih mudah dimaintain dan dibaca.

Jika Anda test, aplikasi akan tetap berjalan seperti sebelumnya.

Memisahkan Routing

Selain memisahkan component diatas, routing juga dapat kita pisahkan dari app-routing.module.ts

Buka file app-routing.module.ts, lalu pindahkan code routing yang berhubungan dengan recipe ke file baru, recipes-routing.module.ts

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";


import { AuthGuardService } from "../auth/auth-guard.service";
import { RecipeDetailComponent } from "./recipe-detail/recipe-detail.component";
import { RecipeEditComponent } from "./recipe-edit/recipe-edit.component";
import { RecipeHomeComponent } from "./recipe-home/recipe-home.component";
import { RecipesResolverService } from "./recipes-resolver.service";
import { RecipesComponent } from "./recipes.component";

const recipeRoutes: Routes = [    
    {path: 'recipes', component: RecipesComponent, canActivate: [AuthGuardService] , children:[  
        {path: '', component: RecipeHomeComponent},
        {path: 'new', component: RecipeEditComponent},
        {path: ':id', component: RecipeDetailComponent, resolve: [RecipesResolverService]},
        {path: ':id/edit', component: RecipeEditComponent, resolve: [RecipesResolverService]}
    ]}
];

@NgModule({
    imports: [RouterModule.forChild(recipeRoutes)],
    exports: [RouterModule]
})
export class RecipesRoutingModule {

}

file app-routing.module.ts

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { AuthComponent } from "./auth/auth.component";
import { ShoppingListComponent } from "./shopping-list/shopping-list.component";

const appRoutes: Routes = [
    {path: '', redirectTo:'/recipes', pathMatch: 'full'},
    {path: 'shopping-list', component: ShoppingListComponent},
    {path: 'auth', component: AuthComponent}
];

@NgModule({
    imports: [RouterModule.forRoot(appRoutes)],
    exports: [RouterModule]
})
export class AppRoutingModule{
}

Jika kita test, aplikasi tetap berjalan seperti sebelumnya.

Sebelumnya digunakan app-routing.module.ts, dimana component declaration recipes perlu di export.

Karena sekarang kita menggunakan routing terpisah, maka pada file recipes.module.ts, sudah tidak diperlukan lagi key property exports.

Berikut isi recipes.module.ts

import { NgModule } from "@angular/core";
import { RouterModule } from "@angular/router";
import { CommonModule } from "@angular/common";
import { ReactiveFormsModule } from "@angular/forms";

import { RecipesComponent } from './recipes.component';
import { RecipeListComponent } from './recipe-list/recipe-list.component';
import { RecipeDetailComponent } from './recipe-detail/recipe-detail.component';
import { RecipeItemComponent } from './recipe-list/recipe-item/recipe-item.component';
import { RecipeHomeComponent } from './recipe-home/recipe-home.component';
import { RecipeEditComponent } from './recipe-edit/recipe-edit.component';
import { RecipesRoutingModule } from "./recipes-routing.module";

@NgModule({
    declarations: [
        RecipesComponent,
        RecipeListComponent,
        RecipeDetailComponent,
        RecipeItemComponent,
        RecipeHomeComponent,
        RecipeEditComponent,
    ],
    imports:[
        CommonModule,
        ReactiveFormsModule,
        RouterModule,
        RecipesRoutingModule
    ],

    //sudah tidak diperlukan
    // exports:[
    //     RecipesComponent,
    //     RecipeListComponent,
    //     RecipeDetailComponent,
    //     RecipeItemComponent,
    //     RecipeHomeComponent,
    //     RecipeEditComponent,
    // ]
})
export class RecipesModule {}

Tips: pemisahan routing berdasarkan fitur kedalam file sendiri cocok digunakan untuk aplikasi yang besar dan kompleks.

Latihan

pisahkan component declarations dan routing untuk fitur shopping-list.

Solusi

file shopping-list/shopping-list.module.ts, akan berisi component declarations yang berhubungan dengan fitur shopping-list. Karena code routing sangat pendek, kita tambahkan code routing disini.

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { RouterModule } from "@angular/router";

import { ShoppingEditComponent } from "./shopping-edit/shopping-edit.component";
import { ShoppingListComponent } from "./shopping-list.component";

@NgModule({
    declarations:[
        ShoppingListComponent,
        ShoppingEditComponent
    ],
    imports:[
        CommonModule,
        FormsModule,
        RouterModule.forChild([
            {path: 'shopping-list', component: ShoppingListComponent}
        ])
    ],
})
export class ShoppingListModule {}

File app-routing.module.ts, path yang berhubungan dengan shopping-list dipindahkan ke file shopping-list.module.ts

import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { AuthComponent } from "./auth/auth.component";

const appRoutes: Routes = [
    {path: '', redirectTo:'/recipes', pathMatch: 'full'},
    {path: 'auth', component: AuthComponent}
];

@NgModule({
    imports: [RouterModule.forRoot(appRoutes)],
    exports: [RouterModule]
})
export class AppRoutingModule{
}

File app.module.ts, deklarasi component yang berhubungan dengan shopping-list dipindahkan kedalam file shopping-list.module.ts

import { NgModule} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {FormsModule, ReactiveFormsModule } from '@angular/forms';
import {HttpClientModule} from '@angular/common/http';

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

import { DropDownDirective } from './shared/dropdown.directive';
import { ShoppingListService } from './shopping-list/shopping-list.service';
import { AppRoutingModule } from './app-routing.module';

import { RecipeService } from './recipes/recipe.service';
import { AuthComponent } from './auth/auth.component'; 
import { LoadingSpinnerComponent } from './shared/loading-spinner/loading-spinner.component';
import { AlertComponent } from './shared/alert/alert.component';
import { PlaceholderDirective } from './shared/placeholder/placeholder.directive';

import { RecipesModule } from './recipes/recipes.module';
import { ShoppingListModule } from './shopping-list/shopping-list.module';

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    DropDownDirective,
    AuthComponent,
    LoadingSpinnerComponent,
    AlertComponent,
    PlaceholderDirective 
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    AppRoutingModule,
    RecipesModule, 
    ShoppingListModule
  ],
  providers: [ShoppingListService, RecipeService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Sampai disini kita sudah berhasil memisahkan module dan routing berdasarkan fitur.

Pada module berikutnya kita akan membahas shared module.

Sharing is caring:

Leave a Comment