mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
docs: add skills for Angular pipes
This commit is contained in:
committed by
Pawel Kozlowski
parent
6ac3e26fe0
commit
6371f0beb1
@@ -82,6 +82,12 @@ When implementing dependency injection in Angular, follow these guidelines:
|
||||
- **Injection Context**: Where `inject()` is allowed, `runInInjectionContext`, and `assertInInjectionContext`. Read [injection-context.md](references/injection-context.md)
|
||||
- **Hierarchical Injectors**: The `EnvironmentInjector` vs `ElementInjector`, resolution rules, modifiers (`optional`, `skipSelf`), and `providers` vs `viewProviders`. Read [hierarchical-injectors.md](references/hierarchical-injectors.md)
|
||||
|
||||
## Pipes
|
||||
|
||||
When formatting values in templates, creating custom pipes, or reusing pipe-like logic in TypeScript, consult the following reference. Prefer pipes in templates; outside templates, avoid injecting pipe classes just to call `transform()`.
|
||||
|
||||
- **Pipes**: Built-in pipe imports, custom pipe naming and implementation, pure vs impure pipes, and TypeScript reuse patterns using standalone formatting functions or extracted plain functions. Read [pipes.md](references/pipes.md)
|
||||
|
||||
## Angular Aria
|
||||
|
||||
When building accessible custom components for any of the following patterns: Accordion, Listbox, Combobox, Menu, Tabs, Toolbar, Tree, Grid, consult the following reference:
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
# 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 {Injectable} from '@angular/core';
|
||||
import {toKebabCase} from './kebab-case';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
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 {Injectable, LOCALE_ID, inject} from '@angular/core';
|
||||
import {formatNumber} from '@angular/common';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
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 {Injectable} from '@angular/core';
|
||||
import {DecimalPipe} from '@angular/common';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
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.
|
||||
Reference in New Issue
Block a user