Angular has lot of built-in directives for listening for events like click, dblclick, mousein, mouseout etc. But sometimes you need something more sophisticated, like detect ctrl-click.
I did not find any directive which would suit my needs, so I had to write my own. Be aware that normal browser behaviour for ctrl-click is to open link in new tab. So you need to be careful, where you use this, as you might confuse the user.
Feel free to remix / reuse the directive as needed. Comments are most welcome.
Happy coding
import { Directive, ElementRef, EventEmitter, OnDestroy, OnInit, Output, Renderer2 } from '@angular/core';
@Directive({
// tslint:disable-next-line:directive-selector
selector: '[ctrl-click]',
})
export class CtrlClickDirective implements OnInit, OnDestroy {
private unsubscribe: any;
// tslint:disable-next-line:no-output-rename
@Output('ctrl-click') ctrlClickEvent = new EventEmitter();
constructor(private readonly renderer: Renderer2, private readonly element: ElementRef) {}
ngOnInit() {
this.unsubscribe = this.renderer.listen(this.element.nativeElement, 'click', event => {
if (event.ctrlKey) {
event.preventDefault();
event.stopPropagation();
// unselect accidentally selected text (browser default behaviour)
document.getSelection().removeAllRanges();
this.ctrlClickEvent.emit(event);
}
});
}
ngOnDestroy() {
if (!this.unsubscribe) {
return;
}
this.unsubscribe();
}
}
Gotcha
You need to be aware of one possible drawback. You can not reliably listen for both (click) and (ctrl-click) on the same element. The (click) event will fire every time. If you need both event listeners, then you need to nest them, like this:
<div (click)="reactToClick()">
<span (ctrl-click)="reactToControlClick()"></span>
</div>