Skip to content

Angular Directives

Directives are Angular's mechanism for attaching behavior to DOM elements. This lesson introduces the three kinds of directives and sets up the deeper lessons on structural and attribute directives that follow.

What Is a Directive?

A directive is a class that can modify the structure, appearance, or behavior of a DOM element. Every Angular component is technically a directive with a template, but Angular distinguishes three categories in practice: components, structural directives, and attribute directives.

Directives let you package reusable DOM behavior, like showing/hiding elements or applying a highlight style, into a single, testable, declarative unit you can drop into any template.

import { Directive, ElementRef, inject } from '@angular/core';

@Directive({
  selector: '[appHighlight]',
  standalone: true,
})
export class HighlightDirective {
  private el = inject(ElementRef);
  constructor() {
    this.el.nativeElement.style.backgroundColor = 'yellow';
  }
}

This attribute directive highlights any element it's applied to: <p appHighlight>Text</p>.

The Three Directive Categories

// 1. Component: a directive with a template
@Component({ selector: 'app-card', ... })

// 2. Structural: changes DOM layout (adds/removes elements)
*ngIf, *ngFor, @if, @for

// 3. Attribute: changes appearance or behavior of an element
[appHighlight], [ngClass], [ngStyle]
  • Component directives always have a template and a selector, they are the UI building blocks you use most.
  • Structural directives add, remove, or repeat elements in the DOM, historically prefixed with *.
  • Attribute directives change the appearance or behavior of an existing element without adding/removing it.
  • You can build your own custom structural or attribute directives with the @Directive decorator.

Angular Directives Cheatsheet

Built-in directives you will use constantly, grouped by category.

Directive Category Purpose
*ngIf / @if Structural Conditionally render an element
*ngFor / @for Structural Repeat an element for each item in a list
*ngSwitch / @switch Structural Render one of several branches
ngClass Attribute Add/remove multiple CSS classes dynamically
ngStyle Attribute Set multiple inline styles dynamically
ngModel Attribute Two-way bind a form control
Custom [appHighlight] Attribute Your own reusable DOM behavior

Why Directives Matter

Without directives, adding conditional rendering, list rendering, or reusable DOM behavior would require manual DOM manipulation scattered throughout component classes. Directives centralize that logic into declarative, reusable template syntax.

  • Keep templates declarative: describe *what* should happen, not imperative DOM manipulation steps.
  • Encourage reuse: one HighlightDirective can be applied to any element across the app.
  • Are fully testable in isolation, just like components and services.

Building a Custom Attribute Directive

Custom directives use the @Directive decorator with a selector, typically an attribute selector wrapped in square brackets so it can be applied to any element.

import { Directive, HostListener, ElementRef, inject } from '@angular/core';

@Directive({
  selector: '[appHoverHighlight]',
  standalone: true,
})
export class HoverHighlightDirective {
  private el = inject(ElementRef);

  @HostListener('mouseenter')
  onEnter() {
    this.el.nativeElement.style.backgroundColor = '#fef08a';
  }

  @HostListener('mouseleave')
  onLeave() {
    this.el.nativeElement.style.backgroundColor = '';
  }
}

@HostListener attaches an event listener directly to the host element the directive is applied to.

Directives vs Components

A component is a directive with a template; a plain directive has no template of its own and instead modifies an existing element. Use a component when you need to render new markup, and a directive when you only need to add behavior to markup that already exists.

Common Mistakes

  • Creating a new component when a lightweight attribute directive would be simpler and avoid extra DOM nesting.
  • Manipulating the DOM directly with document.querySelector instead of using ElementRef and Angular's rendering APIs.
  • Forgetting that custom directive selectors are typically attribute selectors ([appName]), not element selectors.
  • Not marking custom directives standalone: true (or declaring them in a module) before using them.

Key Takeaways

  • Angular directives come in three categories: components, structural, and attribute directives.
  • Structural directives change the DOM layout by adding, removing, or repeating elements.
  • Attribute directives change the appearance or behavior of elements that already exist.
  • You can build custom directives with @Directive, ElementRef, and @HostListener.

Pro Tip

Prefer Angular's renderer APIs or binding syntax over direct DOM manipulation through ElementRef.nativeElement when possible, this keeps your code compatible with server-side rendering, where direct DOM access isn't available.