Writing Your Own Directives
A directive adds behaviour to an element — and you can build your own to reuse little bits of interactivity anywhere.
What you will learn
- Explain what a directive is and the two kinds
- Build an attribute directive with @Directive
- React to events with @HostListener
You have already used directives
A directive is a class that adds behaviour to an element. You have already used built-in ones: *ngIf and *ngFor are structural directives (they add or remove elements), and ngModel is an attribute directive (it changes how an element behaves without adding or removing anything).
The exciting part: you can write your own. If you find yourself repeating the same little behaviour — “highlight on hover”, “auto-focus this input”, “make this text uppercase as you type” — wrap it in a directive once and reuse it everywhere by adding a tiny attribute.
| Kind | What it does | Examples |
|---|---|---|
| Attribute directive | Changes look or behaviour of one element | ngModel, a “highlight” directive |
| Structural directive | Adds or removes elements from the page | *ngIf, *ngFor |
Generate an attribute directive
Like components and services, the CLI makes the file for you.
ng generate directive highlight
# short form: ng g d highlightNote: Output:
CREATE src/app/highlight.directive.ts
You get a class marked with the @Directive decorator, ready for you to fill in the behaviour.
A “highlight on hover” directive
This directive paints an element’s background when the mouse is over it. Two new tools appear: ElementRef gives you the real HTML element so you can change it, and @HostListener runs a method when an event (like mouseenter) happens on the element the directive sits on.
// highlight.directive.ts
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appHighlight]', // used as an attribute
standalone: true
})
export class HighlightDirective {
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onEnter() {
this.el.nativeElement.style.background = 'yellow';
}
@HostListener('mouseleave') onLeave() {
this.el.nativeElement.style.background = '';
}
}Note: Output:
(No visible output by itself — it adds behaviour.)
The selector is [appHighlight] with square brackets, which means “use me as an attribute”. ElementRef hands us the real element; @HostListener runs onEnter when the mouse enters and onLeave when it leaves.
Use it like any attribute
Import the directive into the component that uses it, then add the attribute to any element.
<p appHighlight>Hover over me to see the highlight.</p>Note: Output:
Hover over me to see the highlight.
When the mouse is over the paragraph its background turns yellow; move away and it clears. You can drop appHighlight onto any element to reuse the exact same behaviour.
Tip: Want the directive configurable (say, choose the colour)? Give it an @Input — the same input idea you will meet for components — so you can write <p appHighlight="lightblue">.
Q. What kind of directive is ngModel, which changes an element’s behaviour without adding or removing it?
✍️ Practice
- Build an
appHighlightdirective that changes text colour on hover instead of background. - Add an
@Inputto your directive so the colour can be set from the template.
🏠 Homework
- Create an
appAutofocusdirective that focuses an input when the page loads usingngAfterViewInitor the element’sfocus()method.