Angular Core
Directives
Think of directives as superpowers for your HTML elements. They change the appearance or behavior of any tag without you having to build a completely new component.
Components are great, but sometimes they are overkill. If I just want an image to have a "lazy load" effect, or an input field to automatically focus when the page loads, I don't want to wrap them in a <my-wrapper> component.
That's why I love Directives. They act like "plugins" or "mixins" for your HTML. I write the logic once (e.g., "Make background colorful on hover") and can then attach this capability to any element in my app—whether it's a <div>, a <button>, or another component.
1. The Simulation
I built a simple [appHighlight] directive here. Select a color and hover over the box. Notice that the HTML element itself is dumb; the color logic comes entirely from the directive attached to it.
<div [appHighlight]="#FCD34D">2. Implementation
Building a directive is simpler than a component because it has no template. It only has logic. The core concepts you need to know are ElementRef (to touch the DOM) and @HostListener (to react to the user).
Step 1: The Logic (Directive)
This is the blueprint. By using selector: '[appHighlight]', Angular knows to activate this class whenever it sees that attribute in your HTML.
import { Directive, ElementRef, HostListener, Input, inject } from '@angular/core';
@Directive({
// The square brackets [] mean: This is used as an attribute.
// Usage: <div appHighlight>...</div>
selector: '[appHighlight]',
standalone: true
})
export class HighlightDirective {
// Access the DOM element this directive is attached to
private el = inject(ElementRef);
// Allow configuration from outside (e.g. appHighlight="blue")
@Input() appHighlight = '';
// Listen to native events on the host element
@HostListener('mouseenter') onMouseEnter() {
this.setColor(this.appHighlight || 'yellow');
}
@HostListener('mouseleave') onMouseLeave() {
this.setColor('');
}
private setColor(color: string) {
this.el.nativeElement.style.backgroundColor = color;
this.el.nativeElement.style.transition = 'background-color 0.3s';
}
}Step 2: usage (HTML)
Now we can attach the behavior. A neat trick is using the Input Alias: By naming the @Input() variable the same as the selector, we can pass the color directly in the attribute.
<!-- 1. Simple usage (default color) -->
<p appHighlight>
Hover me (Default)
</p>
<!-- 2. Passing a value (custom color) -->
<!-- Note: We assign the string 'cyan' directly to the directive -->
<div appHighlight="cyan" class="box">
I turn cyan on hover.
</div>
<!-- 3. Works on any tag -->
<button appHighlight="#ff00ff">
Even Buttons!
</button>Attribute vs. Structural: What we built here is an Attribute Directive (changes look/behavior).
There are also Structural Directives (recognizable by the asterisk * like *ngIf or *ngFor). These are more powerful as they can physically add or remove elements from the DOM.