NgModules vs Standalone Components
Older Angular apps wire everything through NgModules; modern Angular uses standalone components — you will meet both.
What you will learn
- Explain what an NgModule was for
- Explain standalone components and why they are simpler
- Recognise both styles when you open a real project
Two ways an Angular app is wired together
Every component needs to know which other pieces it can use — other components, directives, pipes. Angular has had two systems for declaring this, and you will run into both in real codebases.
- NgModules (the old default) — a central
@NgModulefile lists every component, directive and pipe in a feature, plus what it imports and exports. - Standalone components (the modern default, Angular 15+) — each component declares its own imports directly, and there is no NgModule at all.
The old way: an NgModule
In NgModule apps, you register components in a module’s declarations and bring in features through imports. New components must be added to a module before they work.
// app.module.ts (older style)
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { GreetingComponent } from './greeting.component';
@NgModule({
declarations: [AppComponent, GreetingComponent], // your components
imports: [BrowserModule, FormsModule], // features you use
bootstrap: [AppComponent]
})
export class AppModule {}Note: Output:
(No visible output — this is wiring.)
The module declares your components and imports the features they need (like FormsModule for ngModel). Forget to declare a component here and Angular cannot find it — a classic beginner error in older apps.
The modern way: standalone
A standalone component sets standalone: true and lists exactly what it needs in its own imports. No NgModule, less indirection — what a component uses is written right on the component.
// greeting.component.ts (modern standalone style)
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-greeting',
standalone: true,
imports: [FormsModule], // this component’s own needs
template: '<input [(ngModel)]="name"><p>Hi {{ name }}</p>'
})
export class GreetingComponent {
name = '';
}Note: Output:
An input box and a live “Hi …” line.
Everything this component needs (FormsModule) is listed on the component itself — no separate module. This is why the rest of this course used standalone: true throughout.
| NgModule style | Standalone style | |
|---|---|---|
| Where deps are listed | In a central @NgModule | On each component |
| Boilerplate | More | Less |
| Default since | Angular’s early years | Angular 15+ (now default) |
| You’ll see it in | Older / large legacy apps | New projects |
Tip: Write new code as standalone — it is the current default and simpler. But learn to read NgModules too: plenty of existing company codebases still use them, and you will need to maintain those.
Watch out: Do not mix the two carelessly. A standalone component is added to another via its imports list, not by declaring it in an NgModule. Mixing them up produces confusing “component is not a known element” errors.
Q. In a standalone component, where do you list the things it depends on (like FormsModule)?
✍️ Practice
- Open an Angular project and identify whether it uses NgModules or standalone components.
- Convert a small NgModule-declared component into a standalone one.
🏠 Homework
- Write a short note explaining, to a teammate, the difference between NgModule and standalone components and which to use for new code.