Custom directives are a powerful feature in Angular that allows developers to extend HTML by creating reusable behaviors. Whether you’re styling elements dynamically or listening to DOM events, directives are essential for building scalable Angular apps.
In this blog, weβll explore:
- What are custom directives in Angular?
- Types of Angular directives
- Creating attribute directives with real examples
- Structural vs attribute directives
- Best practices and use cases
- Interview questions with detailed answers
π What are Directives in Angular?
In Angular, a directive is a class with a @Directive()
decorator. It lets you attach behavior to DOM elements (like highlighting, showing/hiding elements, etc.) or even modify their structure.
There are three types of directives in Angular:
- Component directives β Have a template, essentially a directive with a view.
- Attribute directives β Change the appearance or behavior of an element (e.g.,
ngStyle
,ngClass
). - Structural directives β Change the DOM layout (e.g.,
*ngIf
,*ngFor
,*ngSwitch
).
β¨ How to Create a Custom Attribute Directive
Letβs build a directive that highlights an element on mouse hover.
π οΈ Step 1: Create the Directive
ng generate directive highlight
This command generates a file highlight.directive.ts
.
β highlight.directive.ts
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() appHighlight = 'yellow';
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.appHighlight);
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight('');
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
π§ͺ Usage in Template
<p [appHighlight]="'lightblue'">Hover me to see custom directive in action!</p>
βοΈ Another Practical Example: AutoFocus Directive
You might want an input field to auto-focus when the page loads.
autofocus.directive.ts
import { Directive, ElementRef, AfterViewInit } from '@angular/core';
@Directive({
selector: '[appAutoFocus]'
})
export class AutoFocusDirective implements AfterViewInit {
constructor(private el: ElementRef) {}
ngAfterViewInit() {
this.el.nativeElement.focus();
}
}
Usage
<input appAutoFocus type="text" placeholder="Auto focused input" />
π Structural Directive Example: Repeat N Times
Letβs create a directive that repeats an element n
times.
repeat.directive.ts
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appRepeat]'
})
export class RepeatDirective {
@Input() set appRepeat(times: number) {
this.vcRef.clear();
for (let i = 0; i < times; i++) {
this.vcRef.createEmbeddedView(this.templateRef);
}
}
constructor(
private templateRef: TemplateRef<any>,
private vcRef: ViewContainerRef
) {}
}
Usage
<div *appRepeat="3">
<p>This will appear 3 times!</p>
</div>
π― When Should You Use Custom Directives?
- Apply reusable logic to DOM elements (e.g.,
hover
,validation
,auto-focus
) - Avoid duplicating structural behavior (e.g., conditional rendering)
- Create reusable UI behavior logic shared across components
β Best Practices
- Keep directive logic simple and reusable.
- Prefer attribute directives for DOM behavior.
- Avoid manipulating DOM directly unless necessary (use
Renderer2
instead). - Always clean up subscriptions or intervals in
ngOnDestroy
.
π€ Angular Interview Questions on Custom Directives
1. What is the difference between a component and a directive in Angular?
Answer: A component is a directive with a template. Directives (like attribute or structural) do not have a view but can modify elements or templates.
2. How do you pass parameters to a directive?
Answer: Use the @Input()
decorator:
@Input() appHighlight: string;
3. What are the lifecycle hooks used in directives?
Answer: Commonly used hooks are ngOnInit
, ngOnChanges
, and ngOnDestroy
. For structural directives, ngAfterViewInit
and ngDoCheck
may also be used.
4. How do structural directives differ from attribute directives?
Answer: Structural directives modify the DOM layout by adding/removing elements (*ngIf
, *ngFor
), while attribute directives modify element behavior/appearance (ngClass
, ngStyle
).
5. How can you build a reusable validation directive?
Answer: Implement Validator
interface, create directive with NG_VALIDATORS
provider.
@Directive({
selector: '[appValidate]',
providers: [{ provide: NG_VALIDATORS, useExisting: ValidateDirective, multi: true }]
})
export class ValidateDirective implements Validator {
validate(control: AbstractControl): ValidationErrors | null {
return control.value === 'admin' ? { forbidden: true } : null;
}
}