Skip to content

Commit 901b7ba

Browse files
committed
fix(material/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 0911820 commit 901b7ba

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
@@ -638,54 +638,54 @@ describe('MDC-based MatCheckbox', () => {
638638
}));
639639
});
640640

641-
describe('aria-label', () => {
642-
let checkboxDebugElement: DebugElement;
643-
let checkboxNativeElement: HTMLElement;
644-
let inputElement: HTMLInputElement;
645-
641+
describe('aria handling', () => {
646642
it('should use the provided aria-label', fakeAsync(() => {
647-
fixture = createComponent(CheckboxWithAriaLabel);
648-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
649-
checkboxNativeElement = checkboxDebugElement.nativeElement;
650-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
643+
fixture = createComponent(CheckboxWithAriaLabel);
644+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
645+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
646+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
651647

652-
fixture.detectChanges();
653-
expect(inputElement.getAttribute('aria-label')).toBe('Super effective');
654-
}));
648+
fixture.detectChanges();
649+
expect(inputElement.getAttribute('aria-label')).toBe('Super effective');
650+
}));
655651

656652
it('should not set the aria-label attribute if no value is provided', fakeAsync(() => {
657-
fixture = createComponent(SingleCheckbox);
658-
fixture.detectChanges();
659-
660-
expect(fixture.nativeElement.querySelector('input').hasAttribute('aria-label'))
661-
.toBe(false);
662-
}));
663-
});
653+
fixture = createComponent(SingleCheckbox);
654+
fixture.detectChanges();
664655

665-
describe('with provided aria-labelledby ', () => {
666-
let checkboxDebugElement: DebugElement;
667-
let checkboxNativeElement: HTMLElement;
668-
let inputElement: HTMLInputElement;
656+
expect(fixture.nativeElement.querySelector('input').hasAttribute('aria-label'))
657+
.toBe(false);
658+
}));
669659

670660
it('should use the provided aria-labelledby', fakeAsync(() => {
671-
fixture = createComponent(CheckboxWithAriaLabelledby);
672-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
673-
checkboxNativeElement = checkboxDebugElement.nativeElement;
674-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
661+
fixture = createComponent(CheckboxWithAriaLabelledby);
662+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
663+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
664+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
675665

676-
fixture.detectChanges();
677-
expect(inputElement.getAttribute('aria-labelledby')).toBe('some-id');
678-
}));
666+
fixture.detectChanges();
667+
expect(inputElement.getAttribute('aria-labelledby')).toBe('some-id');
668+
}));
679669

680670
it('should not assign aria-labelledby if none is provided', fakeAsync(() => {
681-
fixture = createComponent(SingleCheckbox);
682-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
683-
checkboxNativeElement = checkboxDebugElement.nativeElement;
684-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
671+
fixture = createComponent(SingleCheckbox);
672+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
673+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
674+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
675+
676+
fixture.detectChanges();
677+
expect(inputElement.getAttribute('aria-labelledby')).toBe(null);
678+
}));
679+
680+
it('should clear the static aria attributes from the host node', () => {
681+
fixture = createComponent(CheckboxWithStaticAriaAttributes);
682+
const checkbox = fixture.debugElement.query(By.directive(MatCheckbox))!.nativeElement;
683+
fixture.detectChanges();
684+
685+
expect(checkbox.hasAttribute('aria')).toBe(false);
686+
expect(checkbox.hasAttribute('aria-labelledby')).toBe(false);
687+
});
685688

686-
fixture.detectChanges();
687-
expect(inputElement.getAttribute('aria-labelledby')).toBe(null);
688-
}));
689689
});
690690

691691
describe('with provided aria-describedby ', () => {
@@ -1154,3 +1154,8 @@ class CheckboxWithoutLabel {
11541154
@Component({template: `<mat-checkbox tabindex="5"></mat-checkbox>`})
11551155
class CheckboxWithTabindexAttr {
11561156
}
1157+
1158+
@Component({
1159+
template: `<mat-checkbox aria-label="Checkbox" aria-labelledby="something"></mat-checkbox>`
1160+
})
1161+
class CheckboxWithStaticAriaAttributes {}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ const RIPPLE_ANIMATION_CONFIG: RippleAnimationConfig = {
8989
host: {
9090
'class': 'mat-mdc-checkbox',
9191
'[attr.tabindex]': 'null',
92+
'[attr.aria-label]': 'null',
93+
'[attr.aria-labelledby]': 'null',
9294
'[class._mat-animation-noopable]': `_animationMode === 'NoopAnimations'`,
9395
'[class.mdc-checkbox--disabled]': 'disabled',
9496
'[id]': 'id',

src/material/checkbox/checkbox.spec.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -708,16 +708,12 @@ describe('MatCheckbox', () => {
708708
}));
709709
});
710710

711-
describe('aria-label', () => {
712-
let checkboxDebugElement: DebugElement;
713-
let checkboxNativeElement: HTMLElement;
714-
let inputElement: HTMLInputElement;
715-
711+
describe('aria handling', () => {
716712
it('should use the provided aria-label', () => {
717713
fixture = createComponent(CheckboxWithAriaLabel);
718-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
719-
checkboxNativeElement = checkboxDebugElement.nativeElement;
720-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
714+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
715+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
716+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
721717

722718
fixture.detectChanges();
723719
expect(inputElement.getAttribute('aria-label')).toBe('Super effective');
@@ -729,32 +725,36 @@ describe('MatCheckbox', () => {
729725

730726
expect(fixture.nativeElement.querySelector('input').hasAttribute('aria-label')).toBe(false);
731727
});
732-
});
733-
734-
describe('with provided aria-labelledby ', () => {
735-
let checkboxDebugElement: DebugElement;
736-
let checkboxNativeElement: HTMLElement;
737-
let inputElement: HTMLInputElement;
738728

739729
it('should use the provided aria-labelledby', () => {
740730
fixture = createComponent(CheckboxWithAriaLabelledby);
741-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
742-
checkboxNativeElement = checkboxDebugElement.nativeElement;
743-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
731+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
732+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
733+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
744734

745735
fixture.detectChanges();
746736
expect(inputElement.getAttribute('aria-labelledby')).toBe('some-id');
747737
});
748738

749739
it('should not assign aria-labelledby if none is provided', () => {
750740
fixture = createComponent(SingleCheckbox);
751-
checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
752-
checkboxNativeElement = checkboxDebugElement.nativeElement;
753-
inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
741+
const checkboxDebugElement = fixture.debugElement.query(By.directive(MatCheckbox))!;
742+
const checkboxNativeElement = checkboxDebugElement.nativeElement;
743+
const inputElement = <HTMLInputElement>checkboxNativeElement.querySelector('input');
754744

755745
fixture.detectChanges();
756746
expect(inputElement.getAttribute('aria-labelledby')).toBe(null);
757747
});
748+
749+
it('should clear the static aria attributes from the host node', () => {
750+
fixture = createComponent(CheckboxWithStaticAriaAttributes);
751+
const checkbox = fixture.debugElement.query(By.directive(MatCheckbox))!.nativeElement;
752+
fixture.detectChanges();
753+
754+
expect(checkbox.hasAttribute('aria')).toBe(false);
755+
expect(checkbox.hasAttribute('aria-labelledby')).toBe(false);
756+
});
757+
758758
});
759759

760760
describe('with provided aria-describedby ', () => {
@@ -1418,3 +1418,8 @@ class TextBindingComponent {
14181418
@Component({template: `<mat-checkbox></mat-checkbox>`})
14191419
class SimpleCheckbox {
14201420
}
1421+
1422+
@Component({
1423+
template: `<mat-checkbox aria-label="Checkbox" aria-labelledby="something"></mat-checkbox>`
1424+
})
1425+
class CheckboxWithStaticAriaAttributes {}

src/material/checkbox/checkbox.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ const _MatCheckboxMixinBase:
122122
'class': 'mat-checkbox',
123123
'[id]': 'id',
124124
'[attr.tabindex]': 'null',
125+
'[attr.aria-label]': 'null',
126+
'[attr.aria-labelledby]': 'null',
125127
'[class.mat-checkbox-indeterminate]': 'indeterminate',
126128
'[class.mat-checkbox-checked]': 'checked',
127129
'[class.mat-checkbox-disabled]': 'disabled',

0 commit comments

Comments
 (0)