mirror of
https://github.com/angular/skills.git
synced 2026-09-14 16:13:23 +08:00
146 lines
3.8 KiB
Markdown
146 lines
3.8 KiB
Markdown
# Pipes
|
|
|
|
Pipes transform data declaratively inside Angular templates using the `|` operator.
|
|
|
|
## Using pipes in templates
|
|
|
|
Import the pipe class and add it to the component's `imports` array.
|
|
|
|
```ts
|
|
import {Component} from '@angular/core';
|
|
import {DatePipe, CurrencyPipe} from '@angular/common';
|
|
|
|
@Component({
|
|
selector: 'app-invoice',
|
|
imports: [DatePipe, CurrencyPipe],
|
|
template: `
|
|
<p>Date: {{ issuedOn | date: 'mediumDate' }}</p>
|
|
<p>Total: {{ amount | currency }}</p>
|
|
`,
|
|
})
|
|
export class Invoice {
|
|
issuedOn = new Date();
|
|
amount = 49.99;
|
|
}
|
|
```
|
|
|
|
## Using pipe logic outside templates
|
|
|
|
**Do NOT inject pipe classes into services or other classes.** Pipes are template operators, not injectable services. Injecting them causes DI errors in standalone contexts and creates unnecessary coupling.
|
|
|
|
### Custom pipes — extract the transformation function
|
|
|
|
Extract the logic into a plain function. The pipe delegates to it; services import the function directly.
|
|
|
|
```ts
|
|
// kebab-case.ts
|
|
export function toKebabCase(value: string): string {
|
|
return value.toLowerCase().replace(/ /g, '-');
|
|
}
|
|
```
|
|
|
|
```ts
|
|
// kebab-case.pipe.ts
|
|
import {Pipe, PipeTransform} from '@angular/core';
|
|
import {toKebabCase} from './kebab-case';
|
|
|
|
@Pipe({name: 'kebabCase'})
|
|
export class KebabCasePipe implements PipeTransform {
|
|
transform(value: string): string {
|
|
return toKebabCase(value);
|
|
}
|
|
}
|
|
```
|
|
|
|
```ts
|
|
// formatter.service.ts — import the function, NOT the pipe
|
|
import {Service} from '@angular/core';
|
|
import {toKebabCase} from './kebab-case';
|
|
|
|
@Service()
|
|
export class FormatterService {
|
|
toSlug(title: string): string {
|
|
return toKebabCase(title);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Built-in locale-aware pipes — use standalone formatting functions
|
|
|
|
`@angular/common` exports a standalone function for each locale-aware built-in pipe:
|
|
|
|
| Pipe | Standalone function |
|
|
| -------------- | ------------------- |
|
|
| `DatePipe` | `formatDate` |
|
|
| `CurrencyPipe` | `formatCurrency` |
|
|
| `DecimalPipe` | `formatNumber` |
|
|
| `PercentPipe` | `formatPercent` |
|
|
|
|
Inject `LOCALE_ID` to get the current locale and pass it to the function.
|
|
|
|
```ts
|
|
// CORRECT — use formatNumber instead of injecting DecimalPipe
|
|
import {Service, LOCALE_ID, inject} from '@angular/core';
|
|
import {formatNumber} from '@angular/common';
|
|
|
|
@Service()
|
|
export class PriceService {
|
|
private locale = inject(LOCALE_ID);
|
|
|
|
formatQuantity(value: number): string {
|
|
return formatNumber(value, this.locale, '1.0-0');
|
|
}
|
|
}
|
|
```
|
|
|
|
```ts
|
|
// WRONG — do not inject pipe classes
|
|
import {Service, inject} from '@angular/core';
|
|
import {DecimalPipe} from '@angular/common';
|
|
|
|
@Service()
|
|
export class PriceService {
|
|
// ❌ DecimalPipe is not designed to be injected
|
|
private pipe = inject(DecimalPipe);
|
|
}
|
|
```
|
|
|
|
## Creating custom pipes
|
|
|
|
Use the Angular CLI to generate a pipe:
|
|
|
|
```bash
|
|
ng generate pipe path/to/my-pipe
|
|
```
|
|
|
|
A pipe needs a `@Pipe` decorator with a `name` and a `transform` method implementing `PipeTransform`.
|
|
|
|
```ts
|
|
import {Pipe, PipeTransform} from '@angular/core';
|
|
|
|
@Pipe({name: 'truncate'})
|
|
export class TruncatePipe implements PipeTransform {
|
|
transform(value: string, limit = 50): string {
|
|
return value.length > limit ? value.slice(0, limit) + '…' : value;
|
|
}
|
|
}
|
|
```
|
|
|
|
- **`name`**: camelCase. Do not use hyphens.
|
|
- **Class name**: PascalCase version of `name` with `Pipe` appended (e.g., `TruncatePipe`).
|
|
|
|
## Impure pipes
|
|
|
|
Mark a pipe `pure: false` only when you need to detect mutations inside arrays or objects. Impure pipes run on every change-detection cycle and can hurt performance.
|
|
|
|
```ts
|
|
@Pipe({name: 'filterItems', pure: false})
|
|
export class FilterItemsPipe implements PipeTransform {
|
|
transform(items: string[], query: string): string[] {
|
|
return items.filter((i) => i.includes(query));
|
|
}
|
|
}
|
|
```
|
|
|
|
IMPORTANT: Avoid impure pipes unless absolutely necessary.
|