Skip to content

Commit c2a9516

Browse files
devversionkara
authored andcommitted
fix(selection-list): tabIndex should respect disabled state (#7039)
1 parent c3af25b commit c2a9516

File tree

2 files changed

+68
-13
lines changed

2 files changed

+68
-13
lines changed

src/lib/list/selection-list.spec.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,49 @@ describe('MatSelectionList', () => {
270270
});
271271
});
272272

273+
describe('with tabindex', () => {
274+
275+
beforeEach(async(() => {
276+
TestBed.configureTestingModule({
277+
imports: [MatListModule],
278+
declarations: [
279+
SelectionListWithTabindexAttr,
280+
SelectionListWithTabindexBinding,
281+
]
282+
});
283+
284+
TestBed.compileComponents();
285+
}));
286+
287+
it('should properly handle native tabindex attribute', () => {
288+
const fixture = TestBed.createComponent(SelectionListWithTabindexAttr);
289+
const selectionList = fixture.debugElement.query(By.directive(MatSelectionList));
290+
291+
expect(selectionList.componentInstance.tabIndex)
292+
.toBe(5, 'Expected the selection-list tabindex to be set to the attribute value.');
293+
});
294+
295+
it('should support changing the tabIndex through binding', () => {
296+
const fixture = TestBed.createComponent(SelectionListWithTabindexBinding);
297+
const selectionList = fixture.debugElement.query(By.directive(MatSelectionList));
298+
299+
expect(selectionList.componentInstance.tabIndex)
300+
.toBe(0, 'Expected the tabIndex to be set to "0" by default.');
301+
302+
fixture.componentInstance.tabIndex = 3;
303+
fixture.detectChanges();
304+
305+
expect(selectionList.componentInstance.tabIndex)
306+
.toBe(3, 'Expected the tabIndex to updated through binding.');
307+
308+
fixture.componentInstance.disabled = true;
309+
fixture.detectChanges();
310+
311+
expect(selectionList.componentInstance.tabIndex)
312+
.toBe(-1, 'Expected the tabIndex to be set to "-1" if selection list is disabled.');
313+
});
314+
});
315+
273316
describe('with single option', () => {
274317
let fixture: ComponentFixture<SelectionListWithOnlyOneOption>;
275318
let listOption: DebugElement;
@@ -523,3 +566,16 @@ class SelectionListWithSelectedOption {
523566
</mat-selection-list>`})
524567
class SelectionListWithOnlyOneOption {
525568
}
569+
570+
@Component({
571+
template: `<mat-selection-list tabindex="5"></mat-selection-list>`
572+
})
573+
class SelectionListWithTabindexAttr {}
574+
575+
@Component({
576+
template: `<mat-selection-list [tabIndex]="tabIndex" [disabled]="disabled"></mat-selection-list>`
577+
})
578+
class SelectionListWithTabindexBinding {
579+
tabIndex: number;
580+
disabled: boolean;
581+
}

src/lib/list/selection-list.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {SelectionModel} from '@angular/cdk/collections';
1212
import {SPACE} from '@angular/cdk/keycodes';
1313
import {
1414
AfterContentInit,
15+
Attribute,
1516
ChangeDetectionStrategy,
1617
ChangeDetectorRef,
1718
Component,
@@ -32,16 +33,19 @@ import {
3233
import {
3334
CanDisable,
3435
CanDisableRipple,
36+
HasTabIndex,
3537
MatLine,
3638
MatLineSetter,
3739
mixinDisabled,
3840
mixinDisableRipple,
41+
mixinTabIndex,
3942
} from '@angular/material/core';
4043

4144

4245
/** @docs-private */
4346
export class MatSelectionListBase {}
44-
export const _MatSelectionListMixinBase = mixinDisableRipple(mixinDisabled(MatSelectionListBase));
47+
export const _MatSelectionListMixinBase =
48+
mixinTabIndex(mixinDisableRipple(mixinDisabled(MatSelectionListBase)));
4549

4650
/** @docs-private */
4751
export class MatListOptionBase {}
@@ -188,10 +192,10 @@ export class MatListOption extends _MatListOptionMixinBase
188192
moduleId: module.id,
189193
selector: 'mat-selection-list',
190194
exportAs: 'matSelectionList',
191-
inputs: ['disabled', 'disableRipple'],
195+
inputs: ['disabled', 'disableRipple', 'tabIndex'],
192196
host: {
193197
'role': 'listbox',
194-
'[attr.tabindex]': '_tabIndex',
198+
'[tabIndex]': 'tabIndex',
195199
'class': 'mat-selection-list',
196200
'(focus)': 'focus()',
197201
'(keydown)': '_keydown($event)',
@@ -202,11 +206,8 @@ export class MatListOption extends _MatListOptionMixinBase
202206
preserveWhitespaces: false,
203207
changeDetection: ChangeDetectionStrategy.OnPush
204208
})
205-
export class MatSelectionList extends _MatSelectionListMixinBase
206-
implements FocusableOption, CanDisable, CanDisableRipple, AfterContentInit {
207-
208-
/** Tab index for the selection-list. */
209-
_tabIndex = 0;
209+
export class MatSelectionList extends _MatSelectionListMixinBase implements FocusableOption,
210+
CanDisable, CanDisableRipple, HasTabIndex, AfterContentInit {
210211

211212
/** The FocusKeyManager which handles focus. */
212213
_keyManager: FocusKeyManager<MatListOption>;
@@ -217,16 +218,14 @@ export class MatSelectionList extends _MatSelectionListMixinBase
217218
/** The currently selected options. */
218219
selectedOptions: SelectionModel<MatListOption> = new SelectionModel<MatListOption>(true);
219220

220-
constructor(private _element: ElementRef) {
221+
constructor(private _element: ElementRef, @Attribute('tabindex') tabIndex: string) {
221222
super();
223+
224+
this.tabIndex = parseInt(tabIndex) || 0;
222225
}
223226

224227
ngAfterContentInit(): void {
225228
this._keyManager = new FocusKeyManager<MatListOption>(this.options).withWrap();
226-
227-
if (this.disabled) {
228-
this._tabIndex = -1;
229-
}
230229
}
231230

232231
/** Focus the selection-list. */

0 commit comments

Comments
 (0)