Theory
Format for the eye, not the data
FestConnect stores an event fee as the number 49.5 and a date as a raw timestamp. But users should SEE 'Rs 49.50' and '12/07/2026'. You could store formatted strings, but that corrupts the data (you cannot do math on 'Rs 49.50').
The right approach: keep the raw data, and TRANSFORM it only when DISPLAYING. Angular's tool for this is the pipe: a display-only formatter you apply in the template with the | operator. This short lesson covers built-in pipes and how to write your own, so FestConnect's data stays clean while looking polished.
Theory
Pipes, formally
A pipe transforms a value in the TEMPLATE for DISPLAY, WITHOUT changing the underlying data. The syntax uses the | operator:
{{ event.name | uppercase }} shows the name in capitals; the stored value is untouched.
Pipes take arguments after a colon and can chain:
{{ fee | currency:'INR' }}: format as currency{{ today | date:'dd/MM/yyyy' }}: format a date{{ name | lowercase | titlecase }}: chain two pipes
Common built-in pipes: uppercase, lowercase, titlecase, date, currency, percent, slice, json, and async (which unwraps an Observable or Promise right in the template). The key property: pipes are read-only formatting; the source data never changes.
Practical
Built-in pipes and a custom pipe
// In a template:
// {{ 'garba night' | titlecase }} -> Garba Night
// {{ 49.5 | currency:'INR' }} -> currency-formatted fee
// {{ today | date:'dd/MM/yyyy' }} -> 12/07/2026
// A CUSTOM pipe: @Pipe + PipeTransform
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'seatsLabel' })
export class SeatsLabelPipe implements PipeTransform {
transform(seats: number): string {
return seats > 0 ? seats + ' seats left' : 'Sold out';
}
}
// Used in a template: {{ event.seats | seatsLabel }}
// 350 -> "350 seats left" 0 -> "Sold out"
Theory
Writing a custom pipe
When no built-in pipe fits, write your own:
- a class decorated with @Pipe({ name: 'seatsLabel' })
- implementing PipeTransform with a transform(value, ...args) method that returns the transformed value
Then use it in a template like any pipe: {{ event.seats | seatsLabel }}. The custom pipe above turns a seat NUMBER into a friendly LABEL ('350 seats left' or 'Sold out') purely for display.
Comparing to React: React has no pipe syntax; you would call a plain JavaScript function or write an expression in JSX ({seatsLabel(event.seats)}). Angular's pipe is a declarative, reusable formatting tool built into the template language, cleaner for repeated formatting, and a distinctive Angular feature.
Quiz
What does a pipe do to the underlying data when it formats a value like {{ price | currency }}?
- It permanently converts the stored price to a formatted string
- Nothing: a pipe transforms the value only for DISPLAY; the underlying data is unchanged
- It deletes the original value
- It moves the value to a new variable
Show the answer
Nothing: a pipe transforms the value only for DISPLAY; the underlying data is unchanged
A pipe is a DISPLAY-only transform: {{ price | currency }} shows the price formatted as currency in the template, but the underlying price value in the class stays exactly as it was (still the number you can do math on). Option A misunderstands pipes as mutating data, which they never do, that is the whole point (keep clean data, format only for the eye). Option C and D invent destructive behaviour. This separation, raw data in the class, formatting in the template via pipes, is why you should format with pipes rather than storing pre-formatted strings: the data stays usable and the display stays polished.
Think first
Why not just store 'Rs 49.50'?
It would be simpler to store the fee as the string 'Rs 49.50' and display it directly. Why is keeping the raw number 49.5 and using a currency pipe the better design? Then tap.
Show the answer
Because storing 'Rs 49.50' as a string DESTROYS the number's usefulness. You could no longer add fees, sort events by price, apply a discount, or total a bill, because 'Rs 49.50' is text, not a number. Keeping the raw 49.5 preserves all that math, and the currency PIPE formats it for display only when shown, so the data stays computable AND looks right. The same logic applies to dates (store a real date, display with the date pipe) and any formatted value. This is a general principle beyond Angular: separate DATA from PRESENTATION, keep data in its most useful raw form, and format at the edge, for the eye. Pipes are Angular's clean mechanism for that separation.
Watch out
Pipe traps
Storing formatted strings: keep raw data (numbers, dates); format with pipes for display.
Expecting a pipe to change data: pipes are display-only; the source value is unchanged.
Custom pipe without PipeTransform: implement PipeTransform and the transform() method, or it will not work.
Wrong pipe arguments: arguments follow a colon ({{ x | date:'short' }}); check each pipe's expected arguments.
Heavy work in a pipe: pipes run on change detection; keep transform() light.
Theory
Display polished; now capture input properly
Pipes format what FestConnect shows. The other half is what it COLLECTS: forms. Angular offers two form approaches, template-driven (simple, using ngModel) and reactive (powerful, defined in the class), plus validation. The next lesson covers both and when to use each. Then the final Angular lesson, services and dependency injection with HttpClient, connects FestConnect to a real REST API. Forms next.
Summary
Key takeaways
- A pipe transforms a value for DISPLAY only (via the | operator); the underlying data is unchanged.
- Syntax: {{ value | pipeName }}; arguments after a colon ({{ fee | currency:'INR' }}); pipes chain.
- Built-in pipes: uppercase, lowercase, titlecase, date, currency, percent, slice, json, async.
- Custom pipe: a class with @Pipe({name}) implementing PipeTransform's transform(value, ...args) method.
- Keep raw data (numbers, dates) and format with pipes, rather than storing pre-formatted strings.
- Separating data from presentation keeps values computable and display polished.
- Memory hook: pipes format for the eye with |, never touching the data.