fix(focus-trap): warn if initial element is not focusable (#13960)

Currently if the consumer sets the `cdkFocusInitial` group on a non-focusable element, nothing will happen. These changes add a warning if the app is running in dev mode.

Relates to #13953.
This commit is contained in:
Kristiyan Kostadinov
2018-11-07 18:23:35 +00:00
committed by vivian-hu
parent 4be1b06edd
commit 27347b58b4
2 changed files with 30 additions and 0 deletions
@@ -16,6 +16,7 @@ describe('FocusTrap', () => {
FocusTrapWithSvg,
FocusTrapWithoutFocusableElements,
FocusTrapWithAutoCapture,
FocusTrapUnfocusableTarget,
],
});
@@ -138,6 +139,18 @@ describe('FocusTrap', () => {
focusTrapInstance.focusLastTabbableElement();
expect(document.activeElement!.id).toBe('last');
});
it('should warn if the initial focus target is not focusable', () => {
const alternateFixture = TestBed.createComponent(FocusTrapUnfocusableTarget);
alternateFixture.detectChanges();
focusTrapInstance = fixture.componentInstance.focusTrapDirective.focusTrap;
spyOn(console, 'warn');
focusTrapInstance.focusInitialElement();
expect(console.warn).toHaveBeenCalled();
});
});
describe('special cases', () => {
@@ -235,6 +248,16 @@ class FocusTrapTargets {
@ViewChild(CdkTrapFocus) focusTrapDirective: CdkTrapFocus;
}
@Component({
template: `
<div cdkTrapFocus>
<div cdkFocusInitial></div>
</div>
`
})
class FocusTrapUnfocusableTarget {
@ViewChild(CdkTrapFocus) focusTrapDirective: CdkTrapFocus;
}
@Component({
template: `
+7
View File
@@ -18,6 +18,7 @@ import {
NgZone,
OnDestroy,
DoCheck,
isDevMode,
} from '@angular/core';
import {take} from 'rxjs/operators';
import {InteractivityChecker} from '../interactivity-checker/interactivity-checker';
@@ -189,6 +190,12 @@ export class FocusTrap {
`will be removed in 8.0.0`, redirectToElement);
}
// Warn the consumer if the element they've pointed to
// isn't focusable, when not in production mode.
if (isDevMode() && !this._checker.isFocusable(redirectToElement)) {
console.warn(`Element matching '[cdkFocusInitial]' is not focusable.`, redirectToElement);
}
redirectToElement.focus();
return true;
}