Templates & LogicPro· 35 min read

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.

KindWhat it doesExamples
Attribute directiveChanges look or behaviour of one elementngModel, a “highlight” directive
Structural directiveAdds or removes elements from the page*ngIf, *ngFor

Generate an attribute directive

Like components and services, the CLI makes the file for you.

The CLI creates a directive class
ng generate directive highlight
# short form: ng g d highlight

Note: 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.

An attribute directive that highlights on hover
// 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.

Apply the directive by adding its attribute
<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?

Answer: Attribute directives change the look or behaviour of an existing element. Structural directives like *ngIf/*ngFor add or remove elements instead.

✍️ Practice

  1. Build an appHighlight directive that changes text colour on hover instead of background.
  2. Add an @Input to your directive so the colour can be set from the template.

🏠 Homework

  1. Create an appAutofocus directive that focuses an input when the page loads using ngAfterViewInit or the element’s focus() method.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →