I am implementing a virtual keypad in my application but am getting the following error when navigating from my second component to my first component. I created a stackblitz example of the issue.
https://stackblitz.com/edit/onscreen-keyboard-ajten3?file=src/app/app.module.ts
As you will see I can navigate and use the keyboard when I go from the first component to the second component but when I return the the first component then I get an error ERROR Error: object unsubscribed
Here is the code in my directive that controls the subscriptions
import {
Directive,
OnInit,
ElementRef,
Renderer2,
HostListener
} from "@angular/core";
import { KeyboardService } from "./keyboard.service";
import { Subscription } from "rxjs";
@Directive({
selector: "[appOskInput]"
})
export class OskInputDirective implements OnInit {
private keySubscription: Subscription;
private backspaceSubscription: Subscription;
private enterSubscription: Subscription;
private measure: HTMLElement;
constructor(private el: ElementRef, private keyboard: KeyboardService) {}
ngOnInit() {
// TODO I'm sure there's an "Angular way" of doing this
let thisStyle = window.getComputedStyle(this.el.nativeElement);
this.measure = document.createElement("span");
this.measure.style.position = "absolute";
this.measure.style.right = "100%";
this.measure.style.font = thisStyle.font;
document.body.appendChild(this.measure);
}
@HostListener("focus")
private onFocus() {
this.keyboard.fireKeyboardRequested(true);
this.subscribeToKeyboardEvents();
}
@HostListener("blur")
private onBlur() {
this.keyboard.fireKeyboardRequested(false);
this.unsubscribeFromKeyboardEvents();
}
private subscribeToKeyboardEvents() {
this.keySubscription = this.keyboard.keyPressed.subscribe(key =>
this.onKey(key)
);
this.backspaceSubscription = this.keyboard.backspacePressed.subscribe(_ =>
this.onBackspace()
);
this.enterSubscription = this.keyboard.enterPressed.subscribe(_ =>
this.onEnter()
);
}
private unsubscribeFromKeyboardEvents() {
this.keySubscription.unsubscribe();
this.backspaceSubscription.unsubscribe();
this.enterSubscription.unsubscribe();
}
}
Any idea what I can do to fix this?
CodePudding user response:
Dont unsubscribe the source observable this.keyboard.shiftChanged
this is causing the issue, instead add the subscribes of the component to a subscription this.subscription
, and then finally unsubscribe the subscriptions added on ngOnDestroy
.
import {
Directive,
Input,
HostBinding,
HostListener,
OnInit,
OnDestroy,
} from '@angular/core';
import { Subscription } from 'rxjs';
import { KeyboardService } from '../app/keyboard.service';
@Directive({
selector: '[appKeyboardKey]',
})
export class KeyboardKeyDirective implements OnInit, OnDestroy {
private _values: string[];
private isShifted: boolean;
private isAlt: boolean;
subscription: Subscription = new Subscription();
@Input('appKeyboardKey') values: string;
@HostBinding('innerText') currentValue: string;
constructor(private keyboard: KeyboardService) {}
ngOnInit() {
this._values = this.values.split(' ');
this.currentValue = this._values[0];
this.subscription.add(
this.keyboard.shiftChanged.subscribe((shift) => {
this.isShifted = shift;
this.updateCurrentValue();
})
);
this.subscription.add(
this.keyboard.altChanged.subscribe((alt) => {
this.isAlt = alt;
this.updateCurrentValue();
})
);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
updateCurrentValue() {
if (!this.isAlt) {
if (!this.isShifted) {
this.currentValue = this._values[0];
} else {
this.currentValue = this._values[0].toUpperCase();
}
} else {
if (!this.isShifted) {
this.currentValue = this._values[1];
} else {
this.currentValue = this._values[2];
}
}
}
@HostListener('click')
onClick() {
this.keyboard.fireKeyPressed(this.currentValue);
}
}