Reputation: 313
The goal of this is a non-invasive technique to track user actions on desired component behavior... clicks and stuff.
I love how decorators can modify behavior, but I'm not sure if this is impossible or I'm doing it wrong.
If this worked, it would basically behave like a wrapper over the original event handler. I could easily track and untrack events simply by the decoration on the handler. But my goal is to not "dirty" the handler logic with this user tracking layer. It's also convenient that, as-is, the decorator is called with some of the component context, and the context doesn't need to be explicitly coded. That context information could be useful in logging.
app.component.ts
import { Component } from '@angular/core';
import { CaptureUserEvent } from 'app/user-action-tracker';
@Component({
template: `
<h1>
{{title}}
</h1>
<a href="#" (click)="setTitleText($event)">Test</a>
`,
selector: 'app-root',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'app works!';
getElementText(elt:HTMLElement) {
return elt.innerText;
}
@CaptureUserEvent
setTitleText(ev:Event):void {
console.log('called setTitleText');
let newText = this.getElementText(<HTMLElement>ev.target);
this.title = newText;
}
}
user-action-tracker.ts
function CaptureUserEvent(cls, methodName, propertyDefinition):any {
var oldMethod = cls[methodName];
// this ultimately doesn't work... the AppComponent class retains the original function when it runs
cls[methodName] = function (ev:Event) {
console.log('called wrapper');
// log event...
oldMethod(ev);
};
}
export {
CaptureUserEvent
}
Is there a correct way to do this, or something similar that achieves the same goal?
Upvotes: 1
Views: 399
Reputation: 10516
It works if you modify the value of the descriptor:
function CaptureUserEvent(cls, methodName, descriptor): void {
let oldMethod = descriptor.value;
descriptor.value = (ev: Event) => {
console.log('called wrapper');
oldMethod.call(cls, ev);
};
}
Upvotes: 1