Reputation: 3473
I'm trying to create a small Directive to capture the windows global-keyup and then invoke a callback, so I basically captue the global window in a service and the keyup on my Directive:
export class EnterActivationDirective implements OnInit {
private _enterClicked: Action;
@Input() public set enterClicked(action: Action) {
this._enterClicked = action;
}
constructor(public el: ElementRef, public windowWrapperService: WindowWrapperService) {
}
ngOnInit() {
this.windowWrapperService.nativeWindow.onkeyup = this.onWindowKeyUp.bind(this);
}
private onWindowKeyUp(event: any) {
if (event.code === 'Enter' && this._enterClicked) {
this._enterClicked();
}
}
}
The Service and Action-Type aren't that interesting, since the Service just passes the native window and the Action-Type is a generic Callback without any parameters or return-value. The logic itself works, but I get some weird effects regarding the binding to the action. So, one of my other Components registers to the Directive:
<div appEnterActivation [enterClicked]="onKeyUp.bind(this)">
<div>
... Amended
Which then triggers a search-operation:
public search(): void {
this.searchInProgress = true;
const param = this.createSearchParams();
this.searchStarted.emit(param);
this.timeReportEntryApiService.searchTimeReportEntries(param)
.then(f => {
const newObjects = ArrayMapper.MapToNewObjects(f, new TimeReportEntry());
this.searchFinished.emit(newObjects);
this.searchInProgress = false;
}).catch(f => {
this.searchInProgress = false;
throw f;
});
}
public get canSearch(): boolean {
return this.form.valid && !this.searchInProgress;
}
public onKeyUp(): void {
debugger ;
if (this.canSearch) {
this.search();
}
}
Not too much logic here, but if the search is started from the callback, it seems like the properties and functions are in place, but they are on some kind of different object:
Since everything is working with a plain button, I'm almost certain it kindahow has to do with the callback and the binding to this.
I researched a bit regarding this bind, but regarding this thread Use of the JavaScript 'bind' method it seems to be needed. I also tested without binding, but then the this is bound to the global window variable.
Upvotes: 0
Views: 1125
Reputation: 42669
Since you are using TypeScript you can use arrow function, that manages this
correctly.
public onKeyUp = () => {
debugger ;
if (this.canSearch) {
this.search();
}
}
In that case you can just setup the property binding as
[enterClicked]="onKeyUp"
Upvotes: 1
Reputation: 71891
Why are you using an @Input
? Angular made @Output
for such a use case:
template:
<div appEnterActivation (enterClicked)="onEnter()"></div>
class:
export class EnterActivationDirective implements OnInit {
@Output()
public readonly enterClicked: EventEmitter<any> = new EventEmitter();
@HostBinding('document.keyup.enter')
onEnter(): void {
this.enterClicked.emit();
}
}
No need for difficult checks or wrappers :)
Upvotes: 2