Angular Common provides a comprehensive set of pipes for transforming and formatting data in templates, including asynchronous data handling, date/time formatting, text case conversion, number formatting, and internationalization.
Subscribes to Observable or Promise and returns the latest emitted value.
/**
* Subscribes to an Observable or Promise and returns the latest value
* Automatically subscribes when initialized and unsubscribes when destroyed
* Triggers change detection when new values are emitted
*/
export class AsyncPipe implements OnDestroy, PipeTransform {
transform<T>(obj: Observable<T> | Subscribable<T> | Promise<T>): T | null;
transform<T>(obj: null | undefined): null;
transform<T>(obj: Observable<T> | Subscribable<T> | Promise<T> | null | undefined): T | null;
ngOnDestroy(): void;
}Usage Examples:
@Component({
template: `
<!-- Observable data -->
<div *ngIf="user$ | async as user">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
</div>
<!-- Promise data -->
<div>{{ userPromise | async | json }}</div>
<!-- Loading state with async -->
<div *ngIf="(loading$ | async); else content">Loading...</div>
<ng-template #content>
<ul>
<li *ngFor="let item of items$ | async">{{ item.name }}</li>
</ul>
</ng-template>
<!-- HTTP request -->
<pre>{{ httpData$ | async | json }}</pre>
`
})
export class AsyncDataComponent {
user$ = this.userService.getCurrentUser();
items$ = this.itemService.getItems();
loading$ = this.loadingService.isLoading$;
userPromise = this.userService.getUserPromise();
httpData$ = this.http.get<any>('/api/data');
constructor(
private userService: UserService,
private itemService: ItemService,
private loadingService: LoadingService,
private http: HttpClient
) {}
}Formats dates according to locale rules with customizable format strings.
/**
* Formats dates according to locale rules
* Supports various format patterns and timezone conversion
*/
export class DatePipe implements PipeTransform {
transform(value: Date | string | number, format?: string, timezone?: string, locale?: string): string | null;
transform(value: null | undefined, format?: string, timezone?: string, locale?: string): null;
transform(value: Date | string | number | null | undefined, format?: string, timezone?: string, locale?: string): string | null;
}
/** Configuration for DatePipe default behavior */
export interface DatePipeConfig {
dateFormat?: string;
timezone?: string;
}
/** Injection token for DatePipe default options */
export const DATE_PIPE_DEFAULT_OPTIONS: InjectionToken<DatePipeConfig>;
/** @deprecated Use DATE_PIPE_DEFAULT_OPTIONS */
export const DATE_PIPE_DEFAULT_TIMEZONE: InjectionToken<string>;Usage Examples:
@Component({
template: `
<!-- Basic date formatting -->
<p>Default: {{ currentDate | date }}</p>
<p>Short: {{ currentDate | date:'short' }}</p>
<p>Medium: {{ currentDate | date:'medium' }}</p>
<p>Long: {{ currentDate | date:'long' }}</p>
<p>Full: {{ currentDate | date:'full' }}</p>
<!-- Custom formats -->
<p>Custom: {{ currentDate | date:'MMM d, y, h:mm a' }}</p>
<p>ISO: {{ currentDate | date:'yyyy-MM-ddTHH:mm:ss' }}</p>
<p>Time only: {{ currentDate | date:'HH:mm:ss' }}</p>
<p>Date only: {{ currentDate | date:'MMMM d, y' }}</p>
<!-- With timezone -->
<p>UTC: {{ currentDate | date:'medium':'UTC' }}</p>
<p>Pacific: {{ currentDate | date:'medium':'America/Los_Angeles' }}</p>
<!-- With locale -->
<p>French: {{ currentDate | date:'medium':'':'fr' }}</p>
<p>German: {{ currentDate | date:'full':'':'de' }}</p>
<!-- From timestamp -->
<p>From timestamp: {{ timestamp | date:'short' }}</p>
<!-- From string -->
<p>From string: {{ dateString | date:'longDate' }}</p>
`
})
export class DateFormattingComponent {
currentDate = new Date();
timestamp = 1640995200000; // Unix timestamp
dateString = '2024-01-15T10:30:00Z';
}
// Custom DatePipe configuration
@NgModule({
providers: [
{
provide: DATE_PIPE_DEFAULT_OPTIONS,
useValue: {
dateFormat: 'shortDate',
timezone: 'America/New_York'
}
}
]
})
export class AppModule {}Formats numbers with decimal places according to locale rules.
/**
* Formats numbers with decimal places according to locale rules
* Supports custom digit information and locale-specific formatting
*/
export class DecimalPipe implements PipeTransform {
transform(value: number | string, digitsInfo?: string, locale?: string): string | null;
transform(value: null | undefined, digitsInfo?: string, locale?: string): null;
transform(value: number | string | null | undefined, digitsInfo?: string, locale?: string): string | null;
}Formats numbers as percentages according to locale rules.
/**
* Formats numbers as percentages according to locale rules
* Multiplies value by 100 and adds locale-appropriate percent symbol
*/
export class PercentPipe implements PipeTransform {
transform(value: number | string, digitsInfo?: string, locale?: string): string | null;
transform(value: null | undefined, digitsInfo?: string, locale?: string): null;
transform(value: number | string | null | undefined, digitsInfo?: string, locale?: string): string | null;
}Formats numbers as currency according to locale rules with currency symbols.
/**
* Formats numbers as currency according to locale rules
* Supports various display formats and custom currency codes
*/
export class CurrencyPipe implements PipeTransform {
transform(value: number | string, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null;
transform(value: null | undefined, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): null;
transform(value: number | string | null | undefined, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null;
}Usage Examples:
@Component({
template: `
<!-- Decimal formatting -->
<p>Default: {{ 1234.567 | number }}</p>
<p>1-3 digits: {{ 1234.567 | number:'1.1-3' }}</p>
<p>Min 2 digits: {{ 5 | number:'2.0' }}</p>
<p>German locale: {{ 1234.567 | number:'1.2-2':'de' }}</p>
<!-- Percentage formatting -->
<p>Default: {{ 0.259 | percent }}</p>
<p>No decimals: {{ 0.259 | percent:'1.0-0' }}</p>
<p>3 decimals: {{ 0.259 | percent:'1.3-3' }}</p>
<p>French locale: {{ 0.259 | percent:'1.2-2':'fr' }}</p>
<!-- Currency formatting -->
<p>USD Symbol: {{ 1234.56 | currency }}</p>
<p>USD Code: {{ 1234.56 | currency:'USD':'code' }}</p>
<p>EUR Symbol: {{ 1234.56 | currency:'EUR':'symbol' }}</p>
<p>EUR Narrow: {{ 1234.56 | currency:'EUR':'symbol-narrow' }}</p>
<p>Custom digits: {{ 1234.5 | currency:'USD':'symbol':'1.3-3' }}</p>
<p>German EUR: {{ 1234.56 | currency:'EUR':'symbol':'1.2-2':'de' }}</p>
<!-- Dynamic values -->
<p>Price: {{ price | currency:currencyCode:displayType }}</p>
<p>Tax Rate: {{ taxRate | percent:'1.1-1' }}</p>
<p>Score: {{ score | number:'1.0-2' }}</p>
`
})
export class NumberFormattingComponent {
price = 1299.99;
currencyCode = 'USD';
displayType = 'symbol';
taxRate = 0.085; // 8.5%
score = 95.678;
}Transform text case for consistent formatting.
/**
* Transforms text to lowercase
*/
export class LowerCasePipe implements PipeTransform {
transform(value: string): string;
transform(value: null | undefined): null;
transform(value: string | null | undefined): string | null;
}
/**
* Transforms text to uppercase
*/
export class UpperCasePipe implements PipeTransform {
transform(value: string): string;
transform(value: null | undefined): null;
transform(value: string | null | undefined): string | null;
}
/**
* Transforms text to title case (first letter of each word capitalized)
*/
export class TitleCasePipe implements PipeTransform {
transform(value: string): string;
transform(value: null | undefined): null;
transform(value: string | null | undefined): string | null;
}Usage Examples:
@Component({
template: `
<h2>{{ title | titlecase }}</h2>
<p>Username: {{ username | lowercase }}</p>
<p>Code: {{ productCode | uppercase }}</p>
<!-- Dynamic text transformation -->
<div [innerHTML]="formatText(description) | lowercase"></div>
<!-- Chained with other pipes -->
<p>{{ longText | slice:0:50 | titlecase }}</p>
`
})
export class TextTransformComponent {
title = 'welcome to our application';
username = 'JohnDoe123';
productCode = 'abc-def-123';
description = 'THIS IS A DESCRIPTION';
longText = 'this is a very long text that needs to be truncated and formatted';
formatText(text: string): string {
return text.replace(/[^a-zA-Z0-9 ]/g, '');
}
}Converts values to JSON string representation for debugging and display.
/**
* Converts a value to JSON string representation
* Useful for debugging and displaying object data
*/
export class JsonPipe implements PipeTransform {
transform(value: any): string;
}Creates a new array or string containing a subset of elements.
/**
* Creates a new array or string containing a subset of elements
* Supports negative indices and flexible slicing ranges
*/
export class SlicePipe implements PipeTransform {
transform<T>(value: ReadonlyArray<T>, start: number, end?: number): Array<T>;
transform(value: null | undefined, start: number, end?: number): null;
transform<T>(value: ReadonlyArray<T> | null | undefined, start: number, end?: number): Array<T> | null;
transform(value: string, start: number, end?: number): string;
transform(value: string | null | undefined, start: number, end?: number): string | null;
}Transforms objects and maps into arrays of key-value pairs.
/**
* Transforms Object or Map into array of key-value pairs
* Supports custom comparison functions for sorting
*/
export class KeyValuePipe implements PipeTransform {
transform<K, V>(input: ReadonlyMap<K, V>, compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>>;
transform<K extends number, V>(input: Record<K, V>, compareFn?: (a: KeyValue<string, V>, b: KeyValue<string, V>) => number): Array<KeyValue<string, V>>;
transform<K extends string, V>(input: Record<K, V> | ReadonlyMap<K, V>, compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>>;
transform(input: null | undefined, compareFn?: (a: KeyValue<unknown, unknown>, b: KeyValue<unknown, unknown>) => number): null;
transform<K, V>(input: ReadonlyMap<K, V> | Record<string, V> | null | undefined, compareFn?: (a: KeyValue<K, V>, b: KeyValue<K, V>) => number): Array<KeyValue<K, V>> | null;
}
/** Key-value pair interface */
export interface KeyValue<K, V> {
key: K;
value: V;
}
/** Default comparator function for KeyValuePipe */
export function defaultComparator<K, V>(keyValueA: KeyValue<K, V>, keyValueB: KeyValue<K, V>): number;Usage Examples:
@Component({
template: `
<!-- JSON debugging -->
<pre>{{ user | json }}</pre>
<pre>{{ formData | json }}</pre>
<!-- Array slicing -->
<div>Recent items:</div>
<ul>
<li *ngFor="let item of items | slice:0:5">{{ item }}</li>
</ul>
<!-- String slicing -->
<p>Preview: {{ longDescription | slice:0:100 }}...</p>
<!-- Key-value iteration -->
<div>User Properties:</div>
<div *ngFor="let item of userObject | keyvalue">
<strong>{{ item.key }}:</strong> {{ item.value }}
</div>
<!-- Key-value with sorting -->
<div *ngFor="let stat of stats | keyvalue:customComparator">
{{ stat.key }}: {{ stat.value }}
</div>
<!-- Map iteration -->
<div *ngFor="let entry of userMap | keyvalue">
{{ entry.key }} -> {{ entry.value }}
</div>
`
})
export class DataStructureComponent {
user = {
id: 1,
name: 'John Doe',
email: 'john@example.com',
role: 'admin'
};
formData = {
username: 'johndoe',
preferences: ['dark-theme', 'notifications'],
settings: { lang: 'en', timezone: 'UTC' }
};
items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7'];
longDescription = 'This is a very long description that needs to be truncated for display purposes in the UI to prevent layout issues.';
userObject = {
name: 'Alice',
age: 30,
city: 'New York',
occupation: 'Developer'
};
stats = {
views: 1250,
likes: 89,
shares: 23,
comments: 45
};
userMap = new Map([
['admin', 'Administrator'],
['user', 'Regular User'],
['guest', 'Guest User']
]);
customComparator = (a: KeyValue<string, number>, b: KeyValue<string, number>) => {
return b.value - a.value; // Sort by value descending
};
}Selects text based on plural rules for the current locale.
/**
* Maps a number to a plural category string according to locale rules
* Supports ICU plural rules (zero, one, two, few, many, other)
*/
export class I18nPluralPipe implements PipeTransform {
transform(value: number | null | undefined, pluralMap: { [count: string]: string }, locale?: string): string;
}Selects text from a mapping object based on a string key.
/**
* Maps a string value to another string from a selection mapping
* Useful for simple text substitution and selection
*/
export class I18nSelectPipe implements PipeTransform {
transform(value: string | null | undefined, mapping: { [key: string]: string }): string;
}Usage Examples:
@Component({
template: `
<!-- Pluralization -->
<div>
{{ messageCount | i18nPlural: messageMapping }}
</div>
<div>
{{ itemCount | i18nPlural: itemMapping }}
</div>
<!-- Selection mapping -->
<div class="user-status">
Status: {{ userStatus | i18nSelect: statusMapping }}
</div>
<div class="priority">
Priority: {{ taskPriority | i18nSelect: priorityMapping }}
</div>
<!-- Dynamic mappings -->
<div>
{{ notificationCount | i18nPlural: getNotificationMapping() }}
</div>
`
})
export class I18nPipeComponent {
messageCount = 5;
itemCount = 1;
userStatus = 'online';
taskPriority = 'high';
notificationCount = 0;
messageMapping = {
'=0': 'No messages',
'=1': 'One message',
'other': '# messages'
};
itemMapping = {
'=0': 'No items in cart',
'=1': 'One item in cart',
'other': '# items in cart'
};
statusMapping = {
'online': 'π’ Online',
'offline': 'π΄ Offline',
'away': 'π‘ Away',
'busy': 'π΄ Busy'
};
priorityMapping = {
'low': 'π’ Low Priority',
'medium': 'π‘ Medium Priority',
'high': 'π΄ High Priority',
'urgent': 'π¨ Urgent'
};
getNotificationMapping() {
return {
'=0': 'No new notifications',
'=1': 'You have 1 new notification',
'other': 'You have # new notifications'
};
}
}// DatePipe types
export interface DatePipeConfig {
dateFormat?: string;
timezone?: string;
}
export const DATE_PIPE_DEFAULT_OPTIONS: InjectionToken<DatePipeConfig>;
export const DATE_PIPE_DEFAULT_TIMEZONE: InjectionToken<string>; // @deprecated
// KeyValuePipe types
export interface KeyValue<K, V> {
key: K;
value: V;
}
export function defaultComparator<K, V>(keyValueA: KeyValue<K, V>, keyValueB: KeyValue<K, V>): number;
// Common pipes collection
export const COMMON_PIPES = [
AsyncPipe,
UpperCasePipe,
LowerCasePipe,
JsonPipe,
SlicePipe,
DecimalPipe,
PercentPipe,
TitleCasePipe,
CurrencyPipe,
DatePipe,
I18nPluralPipe,
I18nSelectPipe,
KeyValuePipe,
];