Creating a Custom NgModule for Material Components in Angular 9

0
1370

Angular Material provides material design component for Angular apps.

In earlier versions of Angular Material, we could import MaterialModule which imports all components from Angular Material and makes them available in our app. Most of the time we will need to import BrowserAnimationsModule too, as many Material components depend on animations.

// app.module.ts...
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from '@angular/material';
...@NgModule({
...
imports: [
BrowserModule,
BrowserAnimationsModule,
MaterialModule
],
...
export class AppModule { }

We can now use Material components in our app. Here for example, I use Input and Button components.

The issue is that MaterialModule makes it currently not possible for tools to remove unused modules/components in tree-shaking process. The output bundle file from ng build will still include all material components even we don’t use some of them.

Fortunately, Angular Material also provides modules for each component so our app can import only ones that we use. From the example above, instead of importing the whole MaterialModule, we can import only MatInputModule and MatButtonModule into our app.module.ts.

...
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatInputModule, MatButtonModule } from '@angular/material';
...@NgModule({
...
imports: [
BrowserModule,
BrowserAnimationsModule,
MatInputModule,
MatButtonModule
],
...
export class AppModule { }

It looks OK for a few Material component modules. But practically our app needs more than that to create a fully function application. We might end up with importing 10 or 20 Material modules to use in many of our components. Results in AppModule is cluttered with a lengthy list of imported modules.

To keep AppModule clean, we can create another NgModule that takes care of importing Material modules to use. Same idea with moving routing logic to a routing module.

Creating a custom material module

We can create a new NgModule with ng generate module command.

$ ng generate module app-material

Then we import Material component modules in this new AppMaterialModule. Note that we also need to put the same list of modules in NgModule.exports too.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatInputModule, MatButtonModule } from '@angular/material';@NgModule({
imports: [
CommonModule,
MatInputModule,
MatButtonModule
],
exports: [
MatInputModule,
MatButtonModule

]
})
export class AppMaterialModule { }

Then in our AppModule, we can import on AppMaterialModule.

import { AppMaterialModule } from './app-material/app-material.module';
...@NgModule({
...
imports: [
BrowserModule,
BrowserAnimationsModule,
AppMaterialModule
],
...
export class AppModule { }

Later on if the app needs more Material components, we only need to import new component modules in AppMaterialModule while AppModule remains the same.

import {
MatInputModule,
MatButtonModule,
MatSelectModule,
MatToolbarModule
} from '@angular/material';@NgModule({
imports: [
CommonModule,
MatInputModule,
MatButtonModule,
MatSelectModule,
MatToolbarModule

],
exports: [
MatInputModule,
MatButtonModule,
MatSelectModule,
MatToolbarModule

]
})
export class AppMaterialModule { }

Or even better, we can also omit the whole import and leave only the export part if what we want from this AppMaterialModule is only to export Material Modules

import {
MatInputModule,
MatButtonModule,

MatSelectModule,
MatToolbarModule
} from '@angular/material';@NgModule({
exports: [
MatInputModule,
MatButtonModule,

MatSelectModule,
MatToolbarModule

]
})
export class AppMaterialModule { }

To summarize:

  • We move taking care of importing Material component modules into an isolated module: AppMaterialModule.
  • We keep AppModule clean, less cluttered.
  • We use future-proof syntax to import Material component modules. This will still work when MaterialModule is removed.