
Quick answer: Angular directives and pipes both transform what the template shows: directives change how an element behaves, pipes change how a value displays. Angular’s built-in control flow handles the old structural directives, but ngClass and ngStyle still style elements, and pipes such as date, currency and uppercase format values in the template. You can write your own directive or pipe when the built-ins do not fit.The sections below cover Angular directives and pipes in the order you need them: the two kinds of directive, writing your own, then the built-in pipes — and the Angular directives and pipes you can now replace with plain template syntax.
Table of Contents
Structural versus attribute directives
A structural directive adds or removes part of the DOM. For years that meant *ngIf and *ngFor; today the template language’s @if and @for do the same job and those directives are deprecated.
An attribute directive changes an existing element without adding or removing it. The two built-ins you will still import are ngClass and ngStyle.
<p [ngClass]="{ 'text-danger': hasError(), 'text-muted': !hasError() }">
Status
</p>
<div [ngStyle]="{ width: percent() + '%' }"></div>Both take an object whose keys are class names or CSS properties and whose values are booleans or values. That keeps conditional styling in the markup instead of in the class. For a single boolean, prefer the plain binding form — [class.text-danger]="hasError()" — which needs no import at all.
Writing a custom Angular directive
A directive is a class with the @Directive decorator. This one highlights any element it is attached to:
import { Directive, ElementRef, HostListener, inject } from '@angular/core';
@Directive({ selector: '[appHighlight]' })
export class HighlightDirective {
private el = inject(ElementRef<HTMLElement>);
@HostListener('mouseenter') onEnter() {
this.el.nativeElement.style.background = '#ccfbf1';
}
@HostListener('mouseleave') onLeave() {
this.el.nativeElement.style.background = '';
}
}The selector [appHighlight] means “match an attribute named appHighlight”. Use it as <p appHighlight>Hover me</p>. @HostListener subscribes to events on the host element; its partner @HostBinding sets host properties instead of reaching into the DOM directly.
@Directive({ selector: '[appBold]' })
export class BoldDirective {
@HostBinding('style.fontWeight') weight = 'bold';
}Prefer @HostBinding over writing styles through ElementRef. It keeps the component’s view encapsulated and is easier to test.
Built-in Angular directives and pipes you will use often
| Pipe | Example | Result |
|---|---|---|
date | {{ today | date:'mediumDate' }} | Oct 17, 2026 |
currency | {{ price | currency:'USD' }} | $19.99 |
uppercase | {{ name | uppercase }} | ADA LOVELACE |
number | {{ ratio | number:'1.2-2' }} | 0.75 |
slice | {{ items | slice:0:3 }} | First three items |
A pipe is written with a vertical bar. You can chain them: {{ name | lowercase | titlecase }}. Standalone components must import the pipe they use — for example import { CurrencyPipe } from '@angular/common'; — just like any other dependency.
Writing a custom pipe
A pipe is a class that implements PipeTransform. This one truncates long text with an ellipsis:
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'truncate' })
export class TruncatePipe implements PipeTransform {
transform(value: string, limit = 40): string {
return value.length > limit ? value.slice(0, limit) + '...' : value;
}
}Arguments after the pipe name become extra parameters: {{ body | truncate:80 }}. By default a pipe reruns on every change detection cycle. Add pure: true for a pure pipe — the default — which recalculates only when its input changes, and keep expensive work out of pipes that run in long lists.
Next in the series: services and dependency injection. To learn directives and pipes on real UI, Ampersand Academy teaches Angular one-to-one.
Frequently asked questions
What is the difference between a directive and a pipe?
A directive changes the behaviour or appearance of an element. A pipe transforms a value for display, such as formatting a date or a currency amount.
Are ngIf and ngFor still used in Angular?
They still work but are deprecated. Use the @if and @for control flow syntax, which is part of the template language and requires no imports.
What does @HostListener do in a directive?
It subscribes the directive to an event on its host element, such as mouseenter or click, so the directive can respond without adding a template handler.
Why do I have to import a pipe in a standalone component?
Standalone components declare their own dependencies. The pipe it uses, such as CurrencyPipe, must appear in the component’s imports array.
Should I use ngStyle or a CSS class?
Prefer a CSS class when the values are fixed, because the stylesheet is easier to maintain and cache. Use ngStyle or a style binding when the value is computed at runtime.
Last updated on · Written by Dinesh Kumar R

