Skip to content

Commit 3351473

Browse files
committed
fix(checkbox): clear static aria attributes from host nodes
Follow-up from #16938. Clears the aria-* attributes from the host node so that they're not duplicated with the underlying input.
1 parent 4778f49 commit 3351473

File tree

4 files changed

+71
-57
lines changed

4 files changed

+71
-57
lines changed

src/material-experimental/mdc-checkbox/checkbox.spec.ts

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -607,54 +607,54 @@ describe('MatCheckbox', () => {
607607
}));
608608
});
609609

610-
describe('aria-label', () => {
611-
let checkboxDebugElement: DebugElement;
612-
let checkboxNativeElement: HTMLElement;
613-
let inputElement: HTMLInputElement;
614-
610+
describe('aria handling', () => {
615611
it('should use the provided aria-label', fakeAsync(() => {
616-
fixture = createComponent(CheckboxWithAriaLabel);
617-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
618-
checkboxNativeElement = checkboxDebugElement.nativeElement;
619-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
612+
fixture = createComponent(CheckboxWithAriaLabel);
613+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
614+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
615+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
620616

621-
fixture.detectChanges();
622-
expect(inputElement.getAttribute('aria-label')).toBe('Super effective');
623-
}));
617+
fixture.detectChanges();
618+
expect(inputElement.getAttribute('aria-label')).toBe('Super effective');
619+
}));
624620

625621
it('should not set the aria-label attribute if no value is provided', fakeAsync(() => {
626-
fixture = createComponent(SingleCheckbox);
627-
fixture.detectChanges();
628-
629-
expect(fixture.nativeElement.querySelector('input').hasAttribute('aria-label'))
630-
.toBe(false);
631-
}));
632-
});
622+
fixture = createComponent(SingleCheckbox);
623+
fixture.detectChanges();
633624

634-
describe('with provided aria-labelledby ', () => {
635-
let checkboxDebugElement: DebugElement;
636-
let checkboxNativeElement: HTMLElement;
637-
let inputElement: HTMLInputElement;
625+
expect(fixture.nativeElement.querySelector('input').hasAttribute('aria-label'))
626+
.toBe(false);
627+
}));
638628

639629
it('should use the provided aria-labelledby', fakeAsync(() => {
640-
fixture = createComponent(CheckboxWithAriaLabelledby);
641-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
642-
checkboxNativeElement = checkboxDebugElement.nativeElement;
643-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
630+
fixture = createComponent(CheckboxWithAriaLabelledby);
631+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
632+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
633+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
644634

645-
fixture.detectChanges();
646-
expect(inputElement.getAttribute('aria-labelledby')).toBe('some-id');
647-
}));
635+
fixture.detectChanges();
636+
expect(inputElement.getAttribute('aria-labelledby')).toBe('some-id');
637+
}));
648638

649639
it('should not assign aria-labelledby if none is provided', fakeAsync(() => {
650-
fixture = createComponent(SingleCheckbox);
651-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
652-
checkboxNativeElement = checkboxDebugElement.nativeElement;
653-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
640+
fixture = createComponent(SingleCheckbox);
641+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
642+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
643+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
644+
645+
fixture.detectChanges();
646+
expect(inputElement.getAttribute('aria-labelledby')).toBe(null);
647+
}));
648+
649+
it('should clear the static aria attributes from the host node', () => {
650+
fixture = createComponent(CheckboxWithStaticAriaAttributes);
651+
const checkbox = fixture.debugElement.query(By.directive(MatCheckbox))!.nativeElement;
652+
fixture.detectChanges();
653+
654+
expect(checkbox.hasAttribute('aria')).toBe(false);
655+
expect(checkbox.hasAttribute('aria-labelledby')).toBe(false);
656+
});
654657

655-
fixture.detectChanges();
656-
expect(inputElement.getAttribute('aria-labelledby')).toBe(null);
657-
}));
658658
});
659659

660660
describe('with provided tabIndex', () => {
@@ -1038,3 +1038,8 @@ class CheckboxWithoutLabel {
10381038
@Component({template: `<mat-checkbox tabindex="5"></mat-checkbox>`})
10391039
class CheckboxWithTabindexAttr {
10401040
}
1041+
1042+
@Component({
1043+
template: `<mat-checkbox aria-label="Checkbox" aria-labelledby="something"></mat-checkbox>`
1044+
})
1045+
class CheckboxWithStaticAriaAttributes {}

src/material-experimental/mdc-checkbox/checkbox.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ export class MatCheckboxChange {
5656
host: {
5757
'class': 'mat-mdc-checkbox',
5858
'[attr.tabindex]': 'null',
59+
'[attr.aria-label]': 'null',
60+
'[attr.aria-labelledby]': 'null',
5961
'[class.mat-primary]': 'color == "primary"',
6062
'[class.mat-accent]': 'color == "accent"',
6163
'[class.mat-warn]': 'color == "warn"',

src/material/checkbox/checkbox.spec.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -689,16 +689,12 @@ describe('MatCheckbox', () => {
689689
}));
690690
});
691691

692-
describe('aria-label', () => {
693-
let checkboxDebugElement: DebugElement;
694-
let checkboxNativeElement: HTMLElement;
695-
let inputElement: HTMLInputElement;
696-
692+
describe('aria handling', () => {
697693
it('should use the provided aria-label', () => {
698694
fixture = createComponent(CheckboxWithAriaLabel);
699-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
700-
checkboxNativeElement = checkboxDebugElement.nativeElement;
701-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
695+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
696+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
697+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
702698

703699
fixture.detectChanges();
704700
expect(inputElement.getAttribute('aria-label')).toBe('Super effective');
@@ -710,32 +706,36 @@ describe('MatCheckbox', () => {
710706

711707
expect(fixture.nativeElement.querySelector('input').hasAttribute('aria-label')).toBe(false);
712708
});
713-
});
714-
715-
describe('with provided aria-labelledby ', () => {
716-
let checkboxDebugElement: DebugElement;
717-
let checkboxNativeElement: HTMLElement;
718-
let inputElement: HTMLInputElement;
719709

720710
it('should use the provided aria-labelledby', () => {
721711
fixture = createComponent(CheckboxWithAriaLabelledby);
722-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
723-
checkboxNativeElement = checkboxDebugElement.nativeElement;
724-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
712+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
713+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
714+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
725715

726716
fixture.detectChanges();
727717
expect(inputElement.getAttribute('aria-labelledby')).toBe('some-id');
728718
});
729719

730720
it('should not assign aria-labelledby if none is provided', () => {
731721
fixture = createComponent(SingleCheckbox);
732-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
733-
checkboxNativeElement = checkboxDebugElement.nativeElement;
734-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
722+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
723+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
724+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
735725

736726
fixture.detectChanges();
737727
expect(inputElement.getAttribute('aria-labelledby')).toBe(null);
738728
});
729+
730+
it('should clear the static aria attributes from the host node', () => {
731+
fixture = createComponent(CheckboxWithStaticAriaAttributes);
732+
const checkbox = fixture.debugElement.query(By.directive(MatCheckbox))!.nativeElement;
733+
fixture.detectChanges();
734+
735+
expect(checkbox.hasAttribute('aria')).toBe(false);
736+
expect(checkbox.hasAttribute('aria-labelledby')).toBe(false);
737+
});
738+
739739
});
740740

741741
describe('with provided tabIndex', () => {
@@ -1306,3 +1306,8 @@ class CheckboxWithProjectedLabel {}
13061306
class TextBindingComponent {
13071307
text: string = 'Some text';
13081308
}
1309+
1310+
@Component({
1311+
template: `<mat-checkbox aria-label="Checkbox" aria-labelledby="something"></mat-checkbox>`
1312+
})
1313+
class CheckboxWithStaticAriaAttributes {}

src/material/checkbox/checkbox.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ const _MatCheckboxMixinBase:
115115
'class': 'mat-checkbox',
116116
'[id]': 'id',
117117
'[attr.tabindex]': 'null',
118+
'[attr.aria-label]': 'null',
119+
'[attr.aria-labelledby]': 'null',
118120
'[class.mat-checkbox-indeterminate]': 'indeterminate',
119121
'[class.mat-checkbox-checked]': 'checked',
120122
'[class.mat-checkbox-disabled]': 'disabled',

0 commit comments

Comments
 (0)