fix(focus-monitor): implement OnDestroy logic (#9305)

Similarly to most of the other DOM-related services, these changes implement `ngOnDestroy` for the `FocusMonitor` which removes the monitoring from all of the currently-monitored elements.
This commit is contained in:
Kristiyan Kostadinov
2018-01-23 16:57:22 +01:00
committed by Jeremy Elbourn
parent c60483485e
commit 8972bf4e79
2 changed files with 24 additions and 6 deletions
+16 -2
View File
@@ -186,14 +186,28 @@ describe('FocusMonitor', () => {
fixture.detectChanges();
tick();
expect(buttonElement.classList.length)
.toBe(2, 'button should have exactly 2 focus classes');
expect(buttonElement.classList.length).toBe(2, 'button should have exactly 2 focus classes');
focusMonitor.stopMonitoring(buttonElement);
fixture.detectChanges();
expect(buttonElement.classList.length).toBe(0, 'button should not have any focus classes');
}));
it('should remove classes when destroyed', fakeAsync(() => {
buttonElement.focus();
fixture.detectChanges();
tick();
expect(buttonElement.classList.length).toBe(2, 'button should have exactly 2 focus classes');
// Destroy manually since destroying the fixture won't do it.
focusMonitor.ngOnDestroy();
fixture.detectChanges();
expect(buttonElement.classList.length).toBe(0, 'button should not have any focus classes');
}));
});
+8 -4
View File
@@ -42,7 +42,7 @@ type MonitoredElementInfo = {
/** Monitors mouse and keyboard events to determine the cause of focus events. */
@Injectable()
export class FocusMonitor {
export class FocusMonitor implements OnDestroy {
/** The focus origin that the next focus event is a result of. */
private _origin: FocusOrigin = null;
@@ -58,8 +58,8 @@ export class FocusMonitor {
/** The timeout id of the touch timeout, used to cancel timeout later. */
private _touchTimeout: number;
/** Weak map of elements being monitored to their info. */
private _elementInfo = new WeakMap<Element, MonitoredElementInfo>();
/** Map of elements being monitored to their info. */
private _elementInfo = new Map<HTMLElement, MonitoredElementInfo>();
/** A map of global objects to lists of current listeners. */
private _unregisterGlobalListeners = () => {};
@@ -135,7 +135,7 @@ export class FocusMonitor {
* @param element The element to stop monitoring.
*/
stopMonitoring(element: HTMLElement): void {
let elementInfo = this._elementInfo.get(element);
const elementInfo = this._elementInfo.get(element);
if (elementInfo) {
elementInfo.unlisten();
@@ -157,6 +157,10 @@ export class FocusMonitor {
element.focus();
}
ngOnDestroy() {
this._elementInfo.forEach((_info, element) => this.stopMonitoring(element));
}
/** Register necessary event listeners on the document and window. */
private _registerGlobalListeners() {
// Do nothing if we're not on the browser platform.