Angular - Accessing DOM elements in Angular Directives — event.target vs ElementRef
What are directives?
Directives are an Angular construct to extend a behavior or the appearance of a DOM element in a specific way. At its core, it’s just a function that executes as soon as Angular encounters it in the DOM.
import {Directive, ElementRef, HostListener, Renderer2} from '@angular/core';
@Directive({
selector: '[blueOnClick]'
})
export class BlueOnClickDirective {
constructor(private renderer: Renderer2) {
}
@HostListener('click', ['$event'])
changeBackground(): void {
this.renderer.setStyle(event.target, 'background', 'skyblue');
}
}
This changes the background color of an element when we click on it. The @HostListener annotation sets up listeners for the click event.
<div class="awesome-container" blueOnClick>
<h1>Real Madrid</h1>
</div>
This changes the background when we click on the directive.
event.target pitfalls
What happens if we use event.target instead? Clicking on the same div causes both the h1 and the div to change colour.
Why does it apply background colour to the div and h1?
Event bubbling in Javascript
When an event happens on an element, it first runs the handlers on it, then on its parent, then all the way up on other ancestors.
So in our case the click event occurs on the h1 element. The event is not handled on the h1 and bubbles up to our div. Once the event arrives on our div it is handled by our directive.
The captured event then still points to it’s source, which is the h1 element.
To fix our example
import {Directive, ElementRef, HostListener, Renderer2} from '@angular/core';
@Directive({
selector: '[blueOnClick]'
})
export class BlueOnClickDirective {
constructor(private elementRef: ElementRef, private renderer: Renderer2) {
}
@HostListener('click', ['$event'])
changeBackground(): void {
this.renderer.setStyle(this.elementRef.nativeElement, 'background', 'skyblue');
}
}
By using the reference of the element in the constructor, we are able to set the style of the host element event if the event occurred on another element which solves our issue of event bubbling in javascript.
References: