Angular course · Module 3: Modules
NgModules - The Clan System
In this lesson4
In feudal Japan, each clan (han) had its own structure, territory, and resources. In Angular, modules play a similar role - they group related elements and define their scope.
What are NgModules?
NgModules are organizational containers in Angular. Although Standalone Components have been preferred since Angular 17+, knowledge of modules is crucial for:
- Working with legacy projects
- Understanding Angular architecture
- Lazy loading (still popular with modules)
Anatomy of an NgModule
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
// Components of this module
import { SamuraiListComponent } from './samurai-list.component';
import { SamuraiCardComponent } from './samurai-card.component';
import { SamuraiDetailComponent } from './samurai-detail.component';
// Services
import { SamuraiService } from './samurai.service';
@NgModule({
// Components, directives, pipes BELONGING to this module
declarations: [
SamuraiListComponent,
SamuraiCardComponent,
SamuraiDetailComponent
],
// Other modules we NEED
imports: [
CommonModule, // *ngIf, *ngFor, async pipe, etc.
FormsModule // ngModel, template-driven forms
],
// Elements SHARED with other modules
exports: [
SamuraiListComponent,
SamuraiCardComponent
],
// Services available in this module (legacy approach)
providers: [
SamuraiService
]
})
export class SamuraiModule { }A note for Angular 19 and later: components are standalone by default, and such a component cannot be listed in declarations - the compiler reports error NG6008. A component that belongs to an NgModule needs standalone: false in its decorator; a standalone component is added to a module through imports.
@NgModule Decorator Properties
| Property | Description | Example |
|---|---|---|
| declarations | Components, directives, pipes belonging to the module | [MyComponent, MyDirective] |
| imports | Modules we need | [CommonModule, FormsModule] |
| exports | Elements shared externally | [MyComponent] |
| providers | Services (legacy, better to use providedIn) | [MyService] |
| bootstrap | Main component (only AppModule) | [AppComponent] |
AppModule - The Central Castle
// app.module.ts - main application module
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule, // Required for browser applications
AppRoutingModule, // Routing
SamuraiModule, // Our feature module
DojoModule
],
providers: [],
bootstrap: [AppComponent] // Startup component
})
export class AppModule { }Picture a module as a clan - declarations are the warriors who belong to it, imports are the alliances it depends on, exports are the forces it lends to others - and AppModule, with its bootstrap field, is the castle from which the whole application marches out.
Code for this lesson: src/app/app.component.ts
import { Component } from '@angular/core';
import { SamuraiModule } from './samurai/samurai.module';
@Component({
selector: 'app-root',
standalone: true,
imports: [SamuraiModule],
template: `
<div class="dojo">
<header>
<h1>Clans and Provinces</h1>
<p>Module 3: Code Organization in Angular</p>
</header>
<main>
<section class="info-panel">
<h2>Module Structure</h2>
<p>Clans (modules) organize warriors (components) into logical groups.</p>
<ul>
<li>Feature Modules - functionalities</li>
<li>Shared Modules - shared elements</li>
<li>Core Module - singleton services</li>
</ul>
</section>
<section class="demo-panel">
<h2>Samurai Clan (Feature Module)</h2>
<app-samurai-list></app-samurai-list>
</section>
</main>
</div>
`,
styles: [`
.dojo {
font-family: 'Segoe UI', sans-serif;
max-width: 900px;
margin: 0 auto;
padding: 20px;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
min-height: 100vh;
color: #eee;
}
header {
text-align: center;
border-bottom: 2px solid #c9a227;
padding-bottom: 20px;
}
h1 { color: #c9a227; }
h2 { color: #c9a227; }
.info-panel, .demo-panel {
background: rgba(255,255,255,0.05);
border: 1px solid #c9a227;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
ul { list-style: none; padding: 0; }
li::before { content: "» "; }
`]
})
export class AppComponent {}Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What do we put in the 'declarations' property of the @NgModule decorator?
2. Which @NgModule property points to the application's main startup component and appears only in AppModule?
These are 2 of 5 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Horizontal ordering
Arrange the tokens of a single import line for the NgModule decorator from @angular/core:
- Code editor
Complete the @NgModule decorator for the SamuraiModule module with the SamuraiListComponent and SamuraiCardComponent components.
- Click in order
Click the elements in order to build the start of the decorator: @NgModule({
- Vertical ordering
Order the properties inside the @NgModule decorator according to the typical layout (consecutive lines from top):