diff --git a/src/cdk/a11y/focus-monitor/focus-monitor.spec.ts b/src/cdk/a11y/focus-monitor/focus-monitor.spec.ts index 1611aefefc94..d712a5b780cd 100644 --- a/src/cdk/a11y/focus-monitor/focus-monitor.spec.ts +++ b/src/cdk/a11y/focus-monitor/focus-monitor.spec.ts @@ -351,6 +351,7 @@ describe('cdkMonitorFocus', () => { ComplexComponentWithMonitorElementFocus, ComplexComponentWithMonitorSubtreeFocus, ComplexComponentWithMonitorSubtreeFocusAndMonitorElementFocus, + FocusMonitorOnCommentNode, ], }).compileComponents(); }); @@ -548,6 +549,14 @@ describe('cdkMonitorFocus', () => { expect(childElement.classList).toContain('cdk-keyboard-focused'); })); }); + + it('should not throw when trying to monitor focus on a non-element node', () => { + expect(() => { + const fixture = TestBed.createComponent(FocusMonitorOnCommentNode); + fixture.detectChanges(); + fixture.destroy(); + }).not.toThrow(); + }); }); describe('FocusMonitor observable stream', () => { @@ -610,7 +619,14 @@ class ComplexComponentWithMonitorElementFocus {} }) class ComplexComponentWithMonitorSubtreeFocus {} + @Component({ template: `
` }) class ComplexComponentWithMonitorSubtreeFocusAndMonitorElementFocus {} + + +@Component({ + template: `` +}) +class FocusMonitorOnCommentNode {} diff --git a/src/cdk/a11y/focus-monitor/focus-monitor.ts b/src/cdk/a11y/focus-monitor/focus-monitor.ts index d4934912504e..b1e7fdfe0d2f 100644 --- a/src/cdk/a11y/focus-monitor/focus-monitor.ts +++ b/src/cdk/a11y/focus-monitor/focus-monitor.ts @@ -225,13 +225,13 @@ export class FocusMonitor implements OnDestroy { monitor(element: HTMLElement | ElementRef, checkChildren: boolean = false): Observable { - // Do nothing if we're not on the browser platform. - if (!this._platform.isBrowser) { + const nativeElement = coerceElement(element); + + // Do nothing if we're not on the browser platform or the passed in node isn't an element. + if (!this._platform.isBrowser || nativeElement.nodeType !== 1) { return observableOf(null); } - const nativeElement = coerceElement(element); - // If the element is inside the shadow DOM, we need to bind our focus/blur listeners to // the shadow root, rather than the `document`, because the browser won't emit focus events // to the `document`, if focus is moving within the same shadow root. @@ -570,10 +570,11 @@ export class CdkMonitorFocus implements AfterViewInit, OnDestroy { constructor(private _elementRef: ElementRef, private _focusMonitor: FocusMonitor) {} ngAfterViewInit() { + const element = this._elementRef.nativeElement; this._monitorSubscription = this._focusMonitor.monitor( - this._elementRef, - this._elementRef.nativeElement.hasAttribute('cdkMonitorSubtreeFocus')) - .subscribe(origin => this.cdkFocusChange.emit(origin)); + element, + element.nodeType === 1 && element.hasAttribute('cdkMonitorSubtreeFocus')) + .subscribe(origin => this.cdkFocusChange.emit(origin)); } ngOnDestroy() {