Understanding Angular Pipes
Question 1: What are Angular Pipes and what is their purpose?
Answer: Angular Pipes are a feature that allows you to transform and format data in your templates without changing the underlying data. They are used to:
- Transform data display format
- Perform data conversions
- Apply filters
- Format dates, numbers, and text
- Create reusable data transformations
Question 2: What are the built-in pipes in Angular and how do you use them?
Answer: Angular provides several built-in pipes. Here are the most commonly used ones with examples:
@Component({
selector: 'app-pipe-demo',
template: `
<!-- Date Pipe -->
<p>Date: {{ today | date: 'fullDate' }}</p>
<p>Custom Date: {{ today | date: 'dd/MM/yyyy HH:mm' }}</p>
<!-- Currency Pipe -->
<p>Price: {{ price | currency: 'USD' }}</p>
<p>Custom Currency: {{ price | currency: 'EUR':'code' }}</p>
<!-- Decimal Pipe -->
<p>Number: {{ number | number: '1.2-2' }}</p>
<!-- Uppercase/Lowercase Pipes -->
<p>{{ text | uppercase }}</p>
<p>{{ text | lowercase }}</p>
<!-- JSON Pipe -->
<pre>{{ object | json }}</pre>
<!-- Async Pipe -->
<div>{{ observableData$ | async }}</div>
<!-- Slice Pipe -->
<p>{{ array | slice:1:3 }}</p>
<!-- Percent Pipe -->
<p>{{ 0.756 | percent:'1.1-2' }}</p>
`
})
export class PipeDemoComponent {
today = new Date();
price = 42.99;
number = 3.14159;
text = 'Angular Pipes';
object = { name: 'John', age: 30 };
array = [1, 2, 3, 4, 5];
observableData$ = of('Async Data').pipe(delay(1000));
}
Question 3: How do you create a custom pipe in Angular?
Answer: Here’s how to create and use a custom pipe:
// filter-list.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filterList',
// Make it pure: false if you want it to update on all changes
pure: true,
// Available in standalone components
standalone: true
})
export class FilterListPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if (!items || !searchText) {
return items;
}
searchText = searchText.toLowerCase();
return items.filter(item =>
item.name.toLowerCase().includes(searchText)
);
}
}
// usage in component
@Component({
selector: 'app-list',
template: `
<input [(ngModel)]="searchText" placeholder="Search...">
<ul>
@for (item of items | filterList:searchText; track item.id) {
<li>{{ item.name }}</li>
}
</ul>
`,
// Import in standalone component
imports: [FilterListPipe]
})
export class ListComponent {
items = [
{ id: 1, name: 'Angular' },
{ id: 2, name: 'React' },
{ id: 3, name: 'Vue' }
];
searchText = '';
}
Question 4: What is the difference between pure and impure pipes?
Answer: Pure and impure pipes differ in how they handle change detection:
// Pure Pipe (Default)
@Pipe({
name: 'pure',
pure: true // default
})
export class PurePipe implements PipeTransform {
transform(value: any) {
// Only executes when input value reference changes
return value;
}
}
// Impure Pipe
@Pipe({
name: 'impure',
pure: false
})
export class ImpurePipe implements PipeTransform {
transform(value: any) {
// Executes on every change detection cycle
return value;
}
}
Interview Tips 💡
Performance Considerations
- Pure pipes are more performant as they only run on reference changes
- Use pure pipes by default unless you specifically need impure behavior
- Be cautious with impure pipes as they can impact performance
Built-in Pipes Best Practices
// Chaining pipes {{ date | date:'shortDate' | uppercase }} // Using pipe parameters {{ number | number:'1.2-2' }} // Async pipe for automatic subscription handling {{ observable$ | async }}
Common Use Cases
- Date formatting
- Number and currency formatting
- Text transformation
- Filtering lists
- Handling async data
Advanced Pipe Features
// Parameterized pipe @Pipe({ name: 'exponential' }) export class ExponentialPipe implements PipeTransform { transform(value: number, exponent = 1): number { return Math.pow(value, exponent); } } // Usage: {{ 2 | exponential:3 }} outputs 8
Error Handling in Pipes
@Pipe({ name: 'safe' }) export class SafePipe implements PipeTransform { transform(value: any): any { try { // Transform logic return processedValue; } catch (error) { console.error('Pipe error:', error); return value; // Return original value on error } } }
Testing Pipes
describe('FilterListPipe', () => { const pipe = new FilterListPipe(); it('should filter list by search text', () => { const items = [ { name: 'Angular' }, { name: 'React' } ]; const filtered = pipe.transform(items, 'ang'); expect(filtered.length).toBe(1); expect(filtered[0].name).toBe('Angular'); }); });
Remember: In interviews, focus on:
- Understanding when to use pipes vs methods
- Performance implications of pure vs impure pipes
- Best practices for creating custom pipes
- Knowledge of built-in pipes and their parameters
- Async pipe benefits for memory management
- Testing strategies for pipes
- Error handling and edge cases