I have a directive that toggles it's state when clicked. If the state is active, and the user clicks anywhere else on the page, the state should be deactivated.
I have tried to achieve this using the new Renderer2 listen function to dynamically generate a listener to catch the "next click" - the issue here is that the callback function executes as soon as the listener is created! So - one click activates, and then immediately deactivates the element. I'm looking for help understanding why this is happening and what I need to do to address it.
Directive:
import { Directive, ElementRef, Input, Output, HostListener, EventEmitter, Renderer2 } from '@angular/core';
@Directive({
selector: '[emClickToClose]'
})
export class ClickToCloseDirective {
@Input('emClickToClose')
openCtrl: boolean;
@Output()
ctrlUpdate: EventEmitter<boolean> = new EventEmitter();
@HostListener('click', ['$event']) onClick(e: MouseEvent) {
this.openCtrl = !this.openCtrl;
this.ctrlUpdate.emit(this.openCtrl);
if (this.openCtrl) {
const removeRegisteredListener = this.renderer.listen('document', 'click', () => {
console.log('the document was clicked', this.openCtrl);
this.openCtrl = false;
this.ctrlUpdate.emit(this.openCtrl);
removeRegisteredListener();
});
}
}
constructor(private el: ElementRef, private renderer: Renderer2) {
}
}
Events bubble up from child to parent, and since you add an event listener while the event is still propagated, the document being the ultimate parent will receive your click event. You need to stop the propagation of the event by using. e.stopPropagation();
in your click handler.