The main difference is where the pipe is registered/imported.
- Modern standalone Angular: import the pipe directly into the component.
- Older NgModule-based Angular: declare custom pipes in an
NgModule, then make them available through that module.
1. How Are Pipes Imported into Standalone Components?
What is it?
In a standalone component, the pipes required by that component can be imported directly into the component's imports array.
For example:
@Component({
imports: [UpperCasePipe]
})
There is no need for an AppModule just to register the pipe.
Why Do We Need It?
Suppose the template contains:
{{ name | uppercase }}
The component needs access to UpperCasePipe.
With standalone components, we explicitly import what the component uses:
imports: [UpperCasePipe]
This makes the component's dependencies clear.
Full Simple Program — Standalone
app.ts
import { Component } from '@angular/core';
import { UpperCasePipe, DatePipe } from '@angular/common';
@Component({
selector: 'app-root',
standalone: true,
imports: [
UpperCasePipe,
DatePipe
],
templateUrl: './app.html'
})
export class App {
name = 'syed mohamed';
today = new Date();
}
app.html
<h2>Standalone Pipe Example</h2>
<p>
Name: {{ name | uppercase }}
</p>
<p>
Date: {{ today | date:'dd/MM/yyyy' }}
</p>
Output:
Name: SYED MOHAMED
Date: 30/09/2026
Explanation
We import the actual pipe classes:
import {
UpperCasePipe,
DatePipe
} from '@angular/common';
Then add them to:
imports: [
UpperCasePipe,
DatePipe
]
Now the template can use:
{{ name | uppercase }}
{{ today | date:'dd/MM/yyyy' }}
Flow
Standalone Component
↓
imports: [UpperCasePipe, DatePipe]
↓
Template
↓
uppercase / date
Custom Pipe in a Standalone Component
Suppose we have:
gender-pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'gender',
standalone: true
})
export class GenderPipe implements PipeTransform {
transform(value: string): string {
if (value === 'M') {
return 'Male';
}
if (value === 'F') {
return 'Female';
}
return 'Unknown';
}
}
Then import it directly:
import { Component } from '@angular/core';
import { GenderPipe } from './gender-pipe';
@Component({
selector: 'app-root',
standalone: true,
imports: [
GenderPipe
],
template: `
<p>{{ gender | gender }}</p>
`
})
export class App {
gender = 'M';
}
Output:
Male
So the important modern approach is:
Pipe
↓
Import directly into Component
↓
Use in Template
2. How Were Pipes Declared and Imported Using NgModules?
Before standalone components became the preferred approach, Angular applications commonly organized components, directives, and pipes using NgModules.
A custom pipe was generally added to the module's:
declarations: []
Then components belonging to that module could use the pipe.
Full Simple Program — Traditional NgModule
gender.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'gender'
})
export class GenderPipe implements PipeTransform {
transform(value: string): string {
if (value === 'M') {
return 'Male';
}
if (value === 'F') {
return 'Female';
}
return 'Unknown';
}
}
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<h2>Employee</h2>
<p>
Gender: {{ gender | gender }}
</p>
`
})
export class AppComponent {
gender = 'M';
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { GenderPipe } from './gender.pipe';
@NgModule({
declarations: [
AppComponent,
GenderPipe
],
imports: [
BrowserModule
],
bootstrap: [
AppComponent
]
})
export class AppModule {
}
Explanation
The important part is:
declarations: [
AppComponent,
GenderPipe
]
The custom pipe belongs to the AppModule.
Therefore:
AppModule
│
├── AppComponent
│
└── GenderPipe
AppComponent can use:
{{ gender | gender }}
because both belong to the same module compilation scope.
What About Built-in Pipes in NgModule Applications?
Built-in pipes such as:
uppercase
lowercase
date
currency
percent
were not manually declared.
For the root browser module, you typically imported:
imports: [
BrowserModule
]
BrowserModule makes the common Angular directives and pipes available to the root application module.
For feature modules, you commonly imported:
CommonModule
For example:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [
EmployeeComponent
],
imports: [
CommonModule
]
})
export class EmployeeModule {
}
CommonModule provides common functionality including pipes such as:
DatePipe
UpperCasePipe
LowerCasePipe
CurrencyPipe
PercentPipe
Sharing a Custom Pipe Between NgModules
Suppose:
EmployeeModule
OrderModule
ProductModule
all need the same custom pipe.
Traditionally, we could create a shared module.
shared.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { GenderPipe } from './gender.pipe';
@NgModule({
declarations: [
GenderPipe
],
imports: [
CommonModule
],
exports: [
GenderPipe
]
})
export class SharedModule {
}
Then another module imports:
@NgModule({
declarations: [
EmployeeComponent
],
imports: [
CommonModule,
SharedModule
]
})
export class EmployeeModule {
}
The flow becomes:
GenderPipe
↓
declared in SharedModule
↓
exported from SharedModule
↓
EmployeeModule imports SharedModule
↓
EmployeeComponent can use GenderPipe
Standalone vs NgModule Approach
| Standalone | Traditional NgModule |
|---|---|
| Pipe imported directly into component | Custom pipe declared in module |
Uses component imports |
Uses module declarations |
| No module required for registration | NgModule manages compilation scope |
| Dependencies are explicit per component | Dependencies commonly managed at module level |
| Modern Angular approach | Traditional Angular architecture |
Standalone
@Component({
imports: [GenderPipe]
})
Traditional NgModule
@NgModule({
declarations: [
AppComponent,
GenderPipe
]
})
Important: declarations vs imports
This is a common interview question.
In traditional NgModule code, a non-standalone custom pipe goes into:
declarations: [
GenderPipe
]
not:
imports: [
GenderPipe
]
because declarations was used for the module's own:
Components
Directives
Pipes
Whereas imports was used primarily for other NgModules:
imports: [
BrowserModule,
CommonModule,
SharedModule
]
Modern standalone Angular changes this pattern because standalone pipes can be imported directly:
@Component({
imports: [
GenderPipe
]
})
Advantages of Standalone Pipe Imports
- Less NgModule boilerplate.
- Component dependencies are explicit.
- Easier to understand which pipe a component uses.
- Easier composition and reuse.
- Works naturally with standalone components, directives, and pipes.
Disadvantages
There is some repetition if many standalone components independently import the same pipes:
imports: [
DatePipe,
CurrencyPipe,
UpperCasePipe
]
However, this explicit dependency model is generally intentional and supports clearer dependency boundaries.
Key Points
Modern Standalone
Import pipes directly:
@Component({
imports: [
DatePipe,
CurrencyPipe,
GenderPipe
]
})
Traditional NgModule
Declare your custom pipe:
@NgModule({
declarations: [
GenderPipe
]
})
For reusable module-based pipes:
Declare
↓
Export
↓
Import Module
↓
Use Pipe
For built-in pipes in traditional feature modules:
imports: [
CommonModule
]
Interview Questions and Answers
Q1. How do you use a pipe in a standalone component?
Import the standalone pipe directly into the component's imports array.
@Component({
imports: [DatePipe]
})
Q2. How were custom pipes registered with NgModules?
They were declared in the module's declarations array:
@NgModule({
declarations: [
GenderPipe
]
})
Q3. Were custom pipes added to imports in traditional NgModules?
A traditional non-standalone pipe was added to:
declarations: []
not directly to:
imports: []
Q4. How did you share a custom pipe between NgModules?
Declare and export it from one module:
@NgModule({
declarations: [GenderPipe],
exports: [GenderPipe]
})
export class SharedModule {}
Then import SharedModule wherever the pipe is needed.
Q5. What is the role of CommonModule?
CommonModule provides commonly used Angular directives and pipes to NgModule-based feature modules.
imports: [
CommonModule
]
Q6. What is the main difference between standalone and NgModule pipe usage?
Standalone:
Pipe
↓
Component imports Pipe
↓
Template
Traditional NgModule:
Pipe
↓
NgModule declares Pipe
↓
Component belongs to Module
↓
Template
Interview One-Line Answer
In standalone Angular, a pipe can be imported directly into a component's
importsarray; in traditional NgModule-based Angular, a non-standalone custom pipe was declared in an NgModule and exported/imported through modules when it needed to be shared.