Custom event handling inside directives

Loading

In Angular, directives allow you to create reusable functionalities and modify the behavior of elements. Custom event handling inside directives is an essential feature that helps improve code modularity and maintainability. In this guide, we will explore how to handle custom events within Angular directives step by step.


Step 1: Understanding Directives in Angular

Angular provides three types of directives:

  1. Component Directives – These are regular Angular components.
  2. Structural Directives – Modify the DOM structure (*ngIf, *ngFor).
  3. Attribute Directives – Change the behavior of elements (ngClass, ngStyle).

For custom event handling, we use attribute directives since they allow us to add behavior to elements dynamically.


Step 2: Setting Up an Angular Project

Before creating a custom directive, let’s set up an Angular project if you haven’t already:

ng new CustomEventDirectiveApp
cd CustomEventDirectiveApp
ng serve

This will create a new Angular project and start a development server.


Step 3: Creating a Custom Directive

Run the following command to generate a directive:

ng generate directive highlight

This will create two files:

  • highlight.directive.ts
  • highlight.directive.spec.ts (for testing)

Open highlight.directive.ts, and you’ll see the following boilerplate code:

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

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) { }
}

This directive can now be applied to any element using the [appHighlight] selector.


Step 4: Adding Custom Event Handling

Now, let’s modify our directive to handle an event. Suppose we want to highlight a text when the user clicks on it.

Modify the highlight.directive.ts file:

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

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) { }

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

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

Explanation:

  • @HostListener('click') – Listens for click events on the host element.
  • highlight(color: string) – A method that changes the background color.

Now, any element with [appHighlight] will turn yellow when clicked.


Step 5: Emitting Custom Events from Directives

What if we want to emit an event from the directive and capture it in a parent component? We can achieve this using @Output and EventEmitter.

Modify the highlight.directive.ts file:

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

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Output() colorChanged = new EventEmitter<string>();

constructor(private el: ElementRef) {}

@HostListener('click') onClick() {
this.highlight('yellow');
this.colorChanged.emit('yellow'); // Emitting event
}

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

Explanation:

  • @Output() colorChanged = new EventEmitter<string>() – Defines an event emitter.
  • this.colorChanged.emit('yellow') – Emits an event with a value.

Now, the directive can send events to the parent component.


Step 6: Using the Directive in a Component

Modify the app.component.html file:

<h2 appHighlight (colorChanged)="onColorChange($event)">Click me to highlight</h2>
<p>Selected Color: {{ selectedColor }}</p>

Modify app.component.ts:

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

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
selectedColor = '';

onColorChange(color: string) {
this.selectedColor = color;
}
}

Explanation:

  • The (colorChanged) event from appHighlight is bound to onColorChange().
  • When the directive emits an event, selectedColor updates.

Now, when you click the text, it will highlight, and the color name will be displayed.


Step 7: Handling Multiple Events

Let’s extend our directive to support mouseover and mouseout events:

Modify highlight.directive.ts:

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

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Output() colorChanged = new EventEmitter<string>();

constructor(private el: ElementRef) {}

@HostListener('click') onClick() {
this.highlight('yellow');
this.colorChanged.emit('yellow');
}

@HostListener('mouseover') onMouseOver() {
this.highlight('lightblue');
this.colorChanged.emit('lightblue');
}

@HostListener('mouseout') onMouseOut() {
this.highlight('white');
this.colorChanged.emit('white');
}

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

Explanation:

  • onMouseOver() – Changes color to light blue.
  • onMouseOut() – Resets the color to white.

Now, the text color will change on hover and reset on mouseout.


Step 8: Passing Inputs to Directives

We can also pass custom colors using @Input().

Modify highlight.directive.ts:

import { Directive, ElementRef, HostListener, Output, EventEmitter, Input } from '@angular/core';

@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() defaultColor: string = 'yellow';
@Output() colorChanged = new EventEmitter<string>();

constructor(private el: ElementRef) {}

@HostListener('click') onClick() {
this.highlight(this.defaultColor);
this.colorChanged.emit(this.defaultColor);
}

private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}

Modify app.component.html:

<h2 appHighlight [defaultColor]="'red'" (colorChanged)="onColorChange($event)">Click me</h2>

Explanation:

  • @Input() defaultColor – Allows color customization.

Now, clicking will change the background color to red instead of yellow.

Leave a Reply

Your email address will not be published. Required fields are marked *