Reputation: 6042
I'm facing a strange effect with my current Ionic (4) project. Here is my (simplified) task:
I have a matrix of labels modeled as a simple table. I'm listening for KeyEvents and if the right arrow key is pressed, I want to change the class of a cell to make the background green (mark the cell as active).
Here is my code:
document.addEventListener('keyup', key => {
this.keydown(key as KeyboardEvent);
});
...
private keydown(keyEvent: KeyboardEvent) {
if (keyEvent.key === 'ArrowRight') {
this.handleKeyRight();
}
}
...
private handleKeyRight() {
if (/* some conditions */) {
this.editing.SizeType.ViewMatrix.map(vRow => {
const col = vRow.indexOf(this.editing.Size);
if (col > -1) {
if (col < 8) {
this.editing.Size = vRow[col + 1];
return;
}
}
});
}
}
Now let's get to the template:
<ion-label text-center class="input-label"
[class.input-label-editing]="editing.Member === member &&
editing.SizeType === sizeType &&
editing.Size === size">
stuff to show
</ion-label>
And last but not least the SCSS:
.input-label {
border-style: inset;
border-radius: 1px;
}
.input-label-editing {
border-style: inset;
border-radius: 1px;
background: green;
}
Don't ask why I want the labels to look like inputs, that's not the question. Here it comes:
When pressing the right arrow key all the code is executed properly. The next cell in the row is being marked as active in the code but the visible class in the template remains the same. BUT: as soon as I perform a click somewhere in the app the changed class becomes visible and the next cell becomes green.
I've tried changing 'keyup' to 'keydown' as recommended in some posts but nothing happens. Any ideas?
Upvotes: 0
Views: 36
Reputation:
This has to do with change detection.
By using document.addEventListener
, you are coding outside of Angular's context. When you click, Angular then performs a change detection, and discovers that he has something to do.
You can verify this statement by using the change detection strategy set to on push : even with a click, the cell won't turn green.
To resolve that, you can either use ngZone.run
(which I don't recommend), or bind your listener to your component (which I do recommend) :
@HostListener('window:keydown', ['$event'])
keydown(keyEvent: KeyboardEvent) { ... }
Upvotes: 1