From 7e20513991d1437b38f9ca5a1287dae5607596f8 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sat, 3 Nov 2018 11:42:09 +0100 Subject: [PATCH] fix(slide-toggle): redirect focus to underlying input element Currently the `mat-slide-toggle` doesn't redirect focus to the underlying `input` element. This means that things like the focus trap's `cdkFocusInitial` won't work when they're set on the toggle host. These changes add a `tabindex` and set up a `focus` listener to forward focus to the input. Relates to #13953. --- src/lib/slide-toggle/slide-toggle.spec.ts | 11 ++++++++++- src/lib/slide-toggle/slide-toggle.ts | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib/slide-toggle/slide-toggle.spec.ts b/src/lib/slide-toggle/slide-toggle.spec.ts index 8fc548e2fe0e..859f6c9ea54a 100644 --- a/src/lib/slide-toggle/slide-toggle.spec.ts +++ b/src/lib/slide-toggle/slide-toggle.spec.ts @@ -293,6 +293,15 @@ describe('MatSlideToggle without forms', () => { expect(document.activeElement).toBe(inputElement); }); + it('should focus on underlying input element when the host is focused', () => { + expect(document.activeElement).not.toBe(inputElement); + + slideToggleElement.focus(); + fixture.detectChanges(); + + expect(document.activeElement).toBe(inputElement); + }); + it('should set a element class if labelPosition is set to before', () => { expect(slideToggleElement.classList).not.toContain('mat-slide-toggle-label-before'); @@ -355,7 +364,7 @@ describe('MatSlideToggle without forms', () => { fixture.detectChanges(); const slideToggle = fixture.debugElement.query(By.directive(MatSlideToggle)).nativeElement; - expect(slideToggle.getAttribute('tabindex')).toBeFalsy(); + expect(slideToggle.getAttribute('tabindex')).toBe('-1'); })); }); diff --git a/src/lib/slide-toggle/slide-toggle.ts b/src/lib/slide-toggle/slide-toggle.ts index 6c48b2f5dada..35a12836e773 100644 --- a/src/lib/slide-toggle/slide-toggle.ts +++ b/src/lib/slide-toggle/slide-toggle.ts @@ -86,11 +86,12 @@ export const _MatSlideToggleMixinBase: host: { 'class': 'mat-slide-toggle', '[id]': 'id', - '[attr.tabindex]': 'null', + '[attr.tabindex]': '-1', // Needs to be `-1` so it can still receive programmatic focus. '[class.mat-checked]': 'checked', '[class.mat-disabled]': 'disabled', '[class.mat-slide-toggle-label-before]': 'labelPosition == "before"', '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"', + '(focus)': '_inputElement.nativeElement.focus()', }, templateUrl: 'slide-toggle.html', styleUrls: ['slide-toggle.css'],