I created a decorator to help me with handling desktop/mobile events
import { HostListener } from \'@angular/core\';
type MobileAwareEventName =
| \'click
A full implementation of estus answer. This works with inheritance. The only downside is that still requires the component to include injector in the constructor.
Full code on StackBlitz
import { ElementRef, Injector, Renderer2 } from '@angular/core';
function normalizeEventName(eventName: string) {
return typeof document.ontouchstart !== 'undefined'
? eventName
.replace('clickstart', 'touchstart')
.replace('clickmove', 'touchmove')
.replace('clickend', 'touchend')
: eventName
.replace('clickstart', 'mousedown')
.replace('clickmove', 'mousemove')
.replace('clickend', 'mouseup');
}
interface MobileAwareEventComponent {
_macSubscribedEvents?: any[];
injector: Injector;
ngOnDestroy?: () => void;
ngOnInit?: () => void;
}
export function MobileAwareHostListener(eventName: string) {
return (classProto: MobileAwareEventComponent, prop: string) => {
classProto._macSubscribedEvents = [];
const ngOnInitUnmodified = classProto.ngOnInit;
classProto.ngOnInit = function(this: MobileAwareEventComponent) {
if (ngOnInitUnmodified) {
ngOnInitUnmodified.call(this);
}
const renderer = this.injector.get(Renderer2) as Renderer2;
const elementRef = this.injector.get(ElementRef) as ElementRef;
const eventNameRegex = /^(?:(window|document|body):|)(.+)/;
const [, eventTarget, eventTargetedName] = eventName.match(eventNameRegex);
const unlisten = renderer.listen(
eventTarget || elementRef.nativeElement,
normalizeEventName(eventTargetedName),
classProto[prop].bind(this),
);
classProto._macSubscribedEvents.push(unlisten);
};
const ngOnDestroyUnmodified = classProto.ngOnDestroy;
classProto.ngOnDestroy = function(this: MobileAwareEventComponent) {
if (ngOnDestroyUnmodified) {
ngOnDestroyUnmodified.call(this);
}
classProto._macSubscribedEvents.forEach((unlisten) => unlisten());
};
};
}