Custom Directives

Loading concept...

🎨 Angular Custom Directives: Teaching Your HTML New Tricks!


🏠 The Magic Paintbrush Story

Imagine you have a magic paintbrush. When you wave it over any object in your room, that object gets superpowers!

  • Wave it over your toy car → it can now glow in the dark!
  • Wave it over your book → it changes color when you touch it!
  • Wave it over your lamp → it turns on when you clap!

Custom Directives in Angular are exactly like this magic paintbrush!

They give ordinary HTML elements extraordinary abilities.


🎯 What Are Custom Directives?

A directive is a special instruction you attach to an HTML element.

Angular has built-in directives like *ngIf and *ngFor. But what if you want your OWN special behavior?

That’s where Custom Directives come in!

graph TD A[Your HTML Element] --> B[Add Custom Directive] B --> C[Element Gets Superpowers!] C --> D[Changes Color on Click] C --> E[Grows on Hover] C --> F[Anything You Dream Up!]

🛠️ Creating Your First Custom Directive

Let’s build a directive that makes any element turn yellow when clicked.

Step 1: Generate the Directive

ng generate directive highlight

This creates a file called highlight.directive.ts.

Step 2: Write the Directive

import { Directive } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {
  constructor() {
    console.log('Directive is alive!');
  }
}

Step 3: Use It!

<p appHighlight>
  Click me! I have superpowers!
</p>

That’s it! The [appHighlight] in brackets means it’s an attribute directive.


đź‘‚ HostListener: Hearing What Happens

Your directive needs ears to hear events like clicks, mouse movements, and keyboard presses.

HostListener is like giving your directive super-hearing!

The Simple Idea

When something happens → Do something

Real Example

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  @HostListener('click')
  onClick() {
    alert('You clicked me!');
  }

  @HostListener('mouseenter')
  onMouseEnter() {
    console.log('Mouse came in!');
  }

  @HostListener('mouseleave')
  onMouseLeave() {
    console.log('Mouse went out!');
  }
}

What Can HostListener Hear?

Event When It Fires
click User clicks element
mouseenter Mouse goes over element
mouseleave Mouse leaves element
keydown User presses a key
focus Element gets focus

Getting Event Details

Want to know WHICH key was pressed?

@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
  console.log('Key pressed:', event.key);
}

The ['$event'] passes the full event object to your function!


🎨 HostBinding: Changing How It Looks

HostListener hears events. HostBinding changes appearance!

Think of HostBinding as your directive’s paintbrush.

The Simple Idea

Connect a property → Element style changes

Real Example

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  @HostBinding('style.backgroundColor')
  bgColor = 'transparent';

  @HostListener('click')
  onClick() {
    this.bgColor = 'yellow';
  }
}

Magic! When you click, the background turns yellow!

What Can HostBinding Change?

// Change background color
@HostBinding('style.backgroundColor')
bgColor = 'red';

// Change text color
@HostBinding('style.color')
textColor = 'white';

// Add a CSS class
@HostBinding('class.active')
isActive = true;

// Change any attribute
@HostBinding('attr.title')
title = 'Hello!';

Complete Example: Color Toggle

@Directive({
  selector: '[appColorToggle]'
})
export class ColorToggleDirective {

  private isHighlighted = false;

  @HostBinding('style.backgroundColor')
  bgColor = 'white';

  @HostBinding('style.color')
  textColor = 'black';

  @HostListener('click')
  toggle() {
    this.isHighlighted = !this.isHighlighted;

    if (this.isHighlighted) {
      this.bgColor = 'purple';
      this.textColor = 'white';
    } else {
      this.bgColor = 'white';
      this.textColor = 'black';
    }
  }
}

đź”§ ElementRef: Touching the Real Element

Sometimes you need to directly touch the HTML element itself.

ElementRef gives you a direct reference to the actual DOM element.

The Simple Idea

ElementRef = The actual HTML element

Basic Example

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

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor(private el: ElementRef) {
    // Access the real HTML element!
    console.log(el.nativeElement);
  }
}

Changing the Element Directly

@Directive({
  selector: '[appBigText]'
})
export class BigTextDirective {

  constructor(private el: ElementRef) {
    this.el.nativeElement.style.fontSize = '24px';
    this.el.nativeElement.style.fontWeight = 'bold';
  }
}

⚠️ Warning About ElementRef

Directly touching nativeElement works, but it’s not the safest way.

Why? Because:

  • It might not work on all platforms (like server-side rendering)
  • It skips Angular’s safety checks

Better approach: Use Renderer2 (coming next!)


🛡️ Renderer2: The Safe Way to Change Elements

Renderer2 is Angular’s official tool for safely changing elements.

Think of it as wearing safety gloves when painting!

Why Use Renderer2?

ElementRef (Direct) Renderer2 (Safe)
Works in browser only Works everywhere
No security checks XSS protection
Faster but riskier Safer and proper

Basic Example

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

@Directive({
  selector: '[appSafeHighlight]'
})
export class SafeHighlightDirective {

  constructor(
    private el: ElementRef,
    private renderer: Renderer2
  ) {
    // Safe way to set style!
    this.renderer.setStyle(
      this.el.nativeElement,
      'backgroundColor',
      'yellow'
    );
  }
}

Renderer2 Superpowers

// Set a style
this.renderer.setStyle(
  element, 'color', 'blue'
);

// Remove a style
this.renderer.removeStyle(
  element, 'color'
);

// Add a CSS class
this.renderer.addClass(
  element, 'highlight'
);

// Remove a CSS class
this.renderer.removeClass(
  element, 'highlight'
);

// Set an attribute
this.renderer.setAttribute(
  element, 'title', 'Hello!'
);

// Remove an attribute
this.renderer.removeAttribute(
  element, 'title'
);

🎪 Putting It All Together

Here’s a complete directive that uses EVERYTHING we learned!

import {
  Directive,
  ElementRef,
  Renderer2,
  HostListener,
  HostBinding,
  Input
} from '@angular/core';

@Directive({
  selector: '[appMagicBox]'
})
export class MagicBoxDirective {

  @Input() highlightColor = 'yellow';

  @HostBinding('style.transition')
  transition = 'all 0.3s ease';

  @HostBinding('style.cursor')
  cursor = 'pointer';

  constructor(
    private el: ElementRef,
    private renderer: Renderer2
  ) {}

  @HostListener('mouseenter')
  onMouseEnter() {
    this.renderer.setStyle(
      this.el.nativeElement,
      'backgroundColor',
      this.highlightColor
    );
    this.renderer.setStyle(
      this.el.nativeElement,
      'transform',
      'scale(1.05)'
    );
  }

  @HostListener('mouseleave')
  onMouseLeave() {
    this.renderer.removeStyle(
      this.el.nativeElement,
      'backgroundColor'
    );
    this.renderer.setStyle(
      this.el.nativeElement,
      'transform',
      'scale(1)'
    );
  }
}

Using It in HTML

<div appMagicBox highlightColor="coral">
  Hover over me for magic!
</div>

<button appMagicBox highlightColor="#00ff00">
  I glow green!
</button>

🗺️ The Big Picture

graph TD A[Custom Directive] --> B[HostListener] A --> C[HostBinding] A --> D[ElementRef] A --> E[Renderer2] B --> F[Listens to Events] C --> G[Binds to Properties] D --> H[Access DOM Element] E --> I[Safely Modify DOM] F --> J[click, hover, keypress...] G --> K[style, class, attr...] H --> L[nativeElement] I --> M[setStyle, addClass...]

🎓 Quick Reference

Tool Purpose Use When
@Directive Create directive Always - it’s the foundation
HostListener Listen to events Reacting to user actions
HostBinding Bind properties Changing styles/classes
ElementRef Access element Need the actual element
Renderer2 Modify safely Best practice for DOM changes

đź’ˇ Remember This!

  1. Directives = Superpowers for HTML elements
  2. HostListener = Your directive’s ears (hearing events)
  3. HostBinding = Your directive’s paintbrush (changing looks)
  4. ElementRef = The actual element (use carefully)
  5. Renderer2 = The safe way (always prefer this)

You now have the power to teach ANY HTML element new tricks!

Go build something amazing! 🚀

Loading story...

No Story Available

This concept doesn't have a story yet.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

Interactive Preview

Interactive - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Interactive Content

This concept doesn't have interactive content yet.

Cheatsheet Preview

Cheatsheet - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Cheatsheet Available

This concept doesn't have a cheatsheet yet.

Quiz Preview

Quiz - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.

No Quiz Available

This concept doesn't have a quiz yet.