Skip to content

Commit

Permalink
fix(focus-monitor): implement OnDestroy logic (#9305)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto authored and jelbourn committed Jan 23, 2018
1 parent c604834 commit 8972bf4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
18 changes: 16 additions & 2 deletions src/cdk/a11y/focus-monitor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}));

});


Expand Down
12 changes: 8 additions & 4 deletions src/cdk/a11y/focus-monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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 = () => {};
Expand Down Expand Up @@ -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();
Expand All @@ -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.
Expand Down

0 comments on commit 8972bf4

Please sign in to comment.