Data transformation pipes for formatting dates, converting booleans to yes/no displays, processing object keys, handling safe HTML/URLs, and providing template-level data utilities for Angular applications.
Date formatting pipe with configurable format strings and locale support.
/**
* Date formatting pipe with configurable format strings
* Pipe name: _date
*/
class DatePipe implements PipeTransform {
/**
* Transform date value to formatted string
* @param value - Date value (Date object, string, or number timestamp)
* @param formatString - Format string (optional, uses default if not provided)
* @returns Formatted date string
*/
transform(value: Date | string | number, formatString?: string | null): string;
}Usage Examples:
// Template usage
@Component({
template: `
<!-- Basic date formatting -->
<p>Created: {{ createdDate | _date }}</p>
<!-- Custom format strings -->
<p>Short date: {{ createdDate | _date:'MM/dd/yyyy' }}</p>
<p>Long format: {{ createdDate | _date:'EEEE, MMMM d, yyyy' }}</p>
<p>Time only: {{ createdDate | _date:'HH:mm:ss' }}</p>
<p>ISO format: {{ createdDate | _date:'yyyy-MM-ddTHH:mm:ss' }}</p>
<!-- With different input types -->
<p>From string: {{ '2023-12-25' | _date:'MMM dd, yyyy' }}</p>
<p>From timestamp: {{ 1703548800000 | _date:'dd/MM/yyyy' }}</p>
<!-- Dynamic format -->
<p>Dynamic: {{ eventDate | _date:selectedFormat }}</p>
<!-- Null/undefined handling -->
<p>Safe: {{ maybeDate | _date:'yyyy-MM-dd' || 'No date' }}</p>
`
})
export class DateExampleComponent {
createdDate = new Date();
eventDate = new Date('2024-01-15T10:30:00');
maybeDate: Date | null = null;
selectedFormat = 'yyyy/MM/dd HH:mm';
// Available format options
formatOptions = [
{ label: 'Short', value: 'MM/dd/yyyy' },
{ label: 'Medium', value: 'MMM dd, yyyy' },
{ label: 'Long', value: 'EEEE, MMMM dd, yyyy' },
{ label: 'ISO', value: 'yyyy-MM-ddTHH:mm:ss' }
];
}
// Component usage
import { DatePipe } from "@delon/theme";
@Component({
providers: [DatePipe]
})
export class ComponentExample {
constructor(private datePipe: DatePipe) {}
formatDate(date: Date, format: string): string {
return this.datePipe.transform(date, format);
}
getFormattedDates() {
const now = new Date();
return {
short: this.datePipe.transform(now, 'MM/dd/yyyy'),
long: this.datePipe.transform(now, 'EEEE, MMMM dd, yyyy'),
time: this.datePipe.transform(now, 'HH:mm:ss')
};
}
}Boolean to yes/no conversion pipe with icon and text display modes.
/**
* Boolean to yes/no conversion pipe with multiple display modes
* Pipe name: yn
*/
class YNPipe implements PipeTransform {
/**
* Transform boolean value to yes/no display
* @param value - Boolean value to convert
* @param yes - Custom text for true values (optional)
* @param no - Custom text for false values (optional)
* @param mode - Display mode: 'full' (icon + text), 'icon' (icon only), 'text' (text only)
* @param isSafeHtml - Whether to return SafeHtml (for icon mode)
* @returns Formatted yes/no display
*/
transform(
value: boolean,
yes?: string,
no?: string,
mode?: YNMode,
isSafeHtml?: boolean
): SafeHtml | string;
}
type YNMode = 'full' | 'icon' | 'text';
interface YNOptions {
yes?: string;
no?: string;
mode?: YNMode;
isSafeHtml?: boolean;
}
/**
* Utility function for yes/no conversion
* @param value - Boolean value
* @param opt - Conversion options
* @returns Formatted string
*/
function yn(value: boolean, opt?: YNOptions): string;Usage Examples:
// Template usage
@Component({
template: `
<!-- Basic yes/no conversion -->
<p>Active: {{ user.isActive | yn }}</p>
<p>Verified: {{ user.isVerified | yn }}</p>
<!-- Custom text -->
<p>Premium: {{ user.isPremium | yn:'Premium':'Free' }}</p>
<p>Status: {{ user.isOnline | yn:'Online':'Offline' }}</p>
<!-- Different modes -->
<p>Full mode: {{ user.isActive | yn:'Yes':'No':'full' }}</p>
<p>Icon only: {{ user.isActive | yn:'':'':'icon':true }}</p>
<p>Text only: {{ user.isActive | yn:'Enabled':'Disabled':'text' }}</p>
<!-- In tables -->
<table>
<tr *ngFor="let item of items">
<td>{{ item.name }}</td>
<td [innerHTML]="item.featured | yn:'':'':'icon':true"></td>
<td>{{ item.published | yn:'Published':'Draft' }}</td>
</tr>
</table>
<!-- Conditional styling -->
<span
[class.text-success]="user.isActive"
[class.text-danger]="!user.isActive"
>
{{ user.isActive | yn:'Active':'Inactive' }}
</span>
`
})
export class YNExampleComponent {
user = {
isActive: true,
isVerified: false,
isPremium: true,
isOnline: false
};
items = [
{ name: 'Item 1', featured: true, published: true },
{ name: 'Item 2', featured: false, published: false },
{ name: 'Item 3', featured: true, published: true }
];
}
// Component usage with utility function
import { yn } from "@delon/theme";
@Component({})
export class UtilityExample {
getStatusText(isActive: boolean): string {
return yn(isActive, {
yes: 'Active',
no: 'Inactive',
mode: 'text'
});
}
getStatusIcon(isActive: boolean): string {
return yn(isActive, {
mode: 'icon',
isSafeHtml: false
});
}
buildStatusReport() {
const statuses = [
{ name: 'Service A', active: true },
{ name: 'Service B', active: false },
{ name: 'Service C', active: true }
];
return statuses.map(service => ({
...service,
statusText: yn(service.active, { yes: 'Running', no: 'Stopped' })
}));
}
}Object keys to array conversion pipe for template iteration.
/**
* Object keys to array conversion pipe
* Pipe name: keys
*/
class KeysPipe implements PipeTransform {
/**
* Transform object keys to array of key-value pairs
* @param value - Object to extract keys from
* @param keyIsNumber - Whether to treat keys as numbers for sorting
* @returns Array of {key, value} objects
*/
transform(value: any, keyIsNumber?: boolean): any[];
}Usage Examples:
// Template usage
@Component({
template: `
<!-- Basic object iteration -->
<div *ngFor="let item of userStats | keys">
<strong>{{ item.key }}:</strong> {{ item.value }}
</div>
<!-- With numeric keys (sorted) -->
<div *ngFor="let item of monthlyData | keys:true">
Month {{ item.key }}: {{ item.value }} sales
</div>
<!-- Complex objects -->
<div class="config-panel">
<div *ngFor="let setting of appConfig | keys" class="setting-item">
<label>{{ setting.key | titlecase }}:</label>
<span>{{ setting.value }}</span>
</div>
</div>
<!-- Nested object display -->
<div class="user-details">
<h3>User Information</h3>
<dl>
<ng-container *ngFor="let field of userInfo | keys">
<dt>{{ field.key | titlecase }}:</dt>
<dd>
<span *ngIf="!isObject(field.value)">{{ field.value }}</span>
<div *ngIf="isObject(field.value)">
<div *ngFor="let nested of field.value | keys">
{{ nested.key }}: {{ nested.value }}
</div>
</div>
</dd>
</ng-container>
</dl>
</div>
<!-- Dynamic form generation -->
<form>
<div *ngFor="let field of formFields | keys" class="form-group">
<label [for]="field.key">{{ field.value.label }}</label>
<input
[id]="field.key"
[type]="field.value.type"
[placeholder]="field.value.placeholder"
[(ngModel)]="formData[field.key]"
/>
</div>
</form>
`
})
export class KeysExampleComponent {
userStats = {
posts: 45,
followers: 1250,
following: 389,
likes: 2750
};
monthlyData = {
1: 1200,
2: 1450,
3: 1100,
4: 1680,
5: 1920
};
appConfig = {
darkMode: true,
notifications: false,
autoSave: true,
language: 'en'
};
userInfo = {
name: 'John Doe',
email: 'john@example.com',
address: {
street: '123 Main St',
city: 'New York',
zip: '10001'
},
preferences: {
theme: 'dark',
timezone: 'EST'
}
};
formFields = {
firstName: {
label: 'First Name',
type: 'text',
placeholder: 'Enter first name'
},
lastName: {
label: 'Last Name',
type: 'text',
placeholder: 'Enter last name'
},
email: {
label: 'Email',
type: 'email',
placeholder: 'Enter email address'
}
};
formData: any = {};
isObject(value: any): boolean {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
}
// Component usage
import { KeysPipe } from "@delon/theme";
@Component({
providers: [KeysPipe]
})
export class ComponentExample {
constructor(private keysPipe: KeysPipe) {}
getObjectEntries(obj: any): any[] {
return this.keysPipe.transform(obj);
}
processConfigObject(config: Record<string, any>) {
const entries = this.keysPipe.transform(config);
return entries.map(entry => ({
setting: entry.key,
value: entry.value,
type: typeof entry.value
}));
}
}Pipes for bypassing Angular's sanitization for trusted HTML and URLs.
/**
* Safe HTML pipe - bypasses Angular sanitization for trusted HTML
* Pipe name: html
*/
class HTMLPipe implements PipeTransform {
/**
* Transform HTML string to SafeHtml
* @param html - HTML string to mark as safe
* @returns SafeHtml or original string
*/
transform(html: string): string | SafeHtml;
}
/**
* Safe URL pipe - bypasses Angular sanitization for trusted URLs
* Pipe name: url
*/
class URLPipe implements PipeTransform {
/**
* Transform URL string to SafeUrl
* @param url - URL string to mark as safe
* @returns SafeUrl or original string
*/
transform(url: string): string | SafeUrl;
}Usage Examples:
// Template usage
@Component({
template: `
<!-- Safe HTML rendering -->
<div [innerHTML]="userBio | html"></div>
<div [innerHTML]="richTextContent | html"></div>
<!-- Safe URL handling -->
<a [href]="externalLink | url" target="_blank">External Link</a>
<iframe [src]="trustedVideoUrl | url"></iframe>
<!-- Dynamic content -->
<div class="article-content">
<h2>{{ article.title }}</h2>
<div [innerHTML]="article.content | html"></div>
</div>
<!-- User-generated content (be careful!) -->
<div class="comment" *ngFor="let comment of comments">
<strong>{{ comment.author }}</strong>
<div [innerHTML]="sanitizeUserContent(comment.content) | html"></div>
</div>
<!-- Embedded resources -->
<div class="media-gallery">
<img
*ngFor="let image of trustedImages"
[src]="image.url | url"
[alt]="image.alt"
/>
</div>
<!-- Document links -->
<ul class="document-links">
<li *ngFor="let doc of documents">
<a [href]="doc.downloadUrl | url" download>
{{ doc.name }}
</a>
</li>
</ul>
`
})
export class SafePipesExampleComponent {
userBio = '<p>Web developer with <strong>10+ years</strong> experience in <em>Angular</em> and <em>TypeScript</em>.</p>';
richTextContent = `
<div class="rich-content">
<h3>Featured Article</h3>
<p>This is a <a href="https://example.com">trusted link</a> in rich content.</p>
<ul>
<li>Point one</li>
<li>Point two</li>
</ul>
</div>
`;
externalLink = 'https://trusted-external-site.com/resource';
trustedVideoUrl = 'https://trusted-video-host.com/embed/video123';
article = {
title: 'Angular Best Practices',
content: '<p>Learn about <code>@Input()</code> and <code>@Output()</code> decorators...</p>'
};
comments = [
{
author: 'User1',
content: 'Great article! Very helpful.'
},
{
author: 'User2',
content: 'Thanks for sharing this <strong>valuable</strong> information.'
}
];
trustedImages = [
{ url: 'https://trusted-cdn.com/image1.jpg', alt: 'Description 1' },
{ url: 'https://trusted-cdn.com/image2.jpg', alt: 'Description 2' }
];
documents = [
{ name: 'User Manual.pdf', downloadUrl: 'https://trusted-storage.com/manual.pdf' },
{ name: 'API Docs.pdf', downloadUrl: 'https://trusted-storage.com/api-docs.pdf' }
];
sanitizeUserContent(content: string): string {
// Implement proper sanitization for user-generated content
// This is a simplified example - use a proper sanitization library
return content
.replace(/<script[^>]*>.*?<\/script>/gi, '')
.replace(/javascript:/gi, '')
.replace(/on\w+="[^"]*"/gi, '');
}
}
// Component usage with DomSanitizer
import { HTMLPipe, URLPipe } from "@delon/theme";
import { DomSanitizer } from "@angular/platform-browser";
@Component({
providers: [HTMLPipe, URLPipe]
})
export class ComponentExample {
constructor(
private htmlPipe: HTMLPipe,
private urlPipe: URLPipe,
private sanitizer: DomSanitizer
) {}
createSafeHtml(content: string): SafeHtml {
return this.htmlPipe.transform(content) as SafeHtml;
}
createSafeUrl(url: string): SafeUrl {
return this.urlPipe.transform(url) as SafeUrl;
}
processTrustedContent(htmlContent: string, resourceUrl: string) {
return {
safeHtml: this.createSafeHtml(htmlContent),
safeUrl: this.createSafeUrl(resourceUrl)
};
}
}