Skip to content

Commit bbb547c

Browse files
authored
Merge pull request #15879 from IgniteUI/ikitanov/fix-15839
Preventing aria-label to defualt to id - 20.0.x
2 parents a9d8f8c + fd19a92 commit bbb547c

File tree

6 files changed

+96
-5
lines changed

6 files changed

+96
-5
lines changed

projects/igniteui-angular/src/lib/combo/combo.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ describe('igxCombo', () => {
10741074

10751075
const list = fixture.debugElement.query(By.css(`.${CSS_CLASS_CONTENT}`));
10761076
expect(list.nativeElement.getAttribute('aria-multiselectable')).toEqual('true');
1077-
expect(list.nativeElement.getAttribute('aria-activedescendant')).toEqual('');
1077+
expect(list.nativeElement.getAttribute('aria-activedescendant')).toEqual(null);
10781078

10791079
UIInteractions.triggerEventHandlerKeyDown('ArrowDown', list);
10801080
tick();

projects/igniteui-angular/src/lib/drop-down/drop-down-item.base.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ export class IgxDropDownItemBaseDirective implements DoCheck {
3434

3535
@HostBinding('attr.aria-label')
3636
@Input()
37-
public get ariaLabel(): string {
38-
return this._label ? this._label : this.value ? this.value : this.id;
37+
public get ariaLabel(): string | null{
38+
return this._label ? this._label : this.value ? this.value : null;
3939
}
4040

41-
public set ariaLabel(value: string) {
41+
public set ariaLabel(value: string | null) {
4242
this._label = value;
4343
}
4444

projects/igniteui-angular/src/lib/drop-down/drop-down-navigation.directive.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Directive, Optional, Self, Input, HostListener, Inject } from '@angular/core';
1+
import { Directive, Optional, Self, Input, HostListener, Inject, HostBinding } from '@angular/core';
22
import { IGX_DROPDOWN_BASE } from './drop-down.common';
33
import { IDropDownNavigationDirective } from './drop-down.common';
44
import { IgxDropDownBaseDirective } from './drop-down.base';
@@ -53,6 +53,11 @@ export class IgxDropDownItemNavigationDirective implements IDropDownNavigationDi
5353
this._target = target ? target : this.dropdown;
5454
}
5555

56+
@HostBinding('attr.aria-activedescendant')
57+
public get activeDescendant(): string {
58+
return this._target?.activeDescendant;
59+
}
60+
5661
/**
5762
* Captures keydown events and calls the appropriate handlers on the target component
5863
*/

projects/igniteui-angular/src/lib/drop-down/drop-down.base.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@ export abstract class IgxDropDownBaseDirective implements IDropDownList, OnInit
162162
return this.element;
163163
}
164164

165+
/**
166+
* @hidden @internal
167+
* Gets the id of the focused item during dropdown navigation.
168+
* This is used to update the `aria-activedescendant` attribute of
169+
* the IgxDropDownNavigationDirective host element.
170+
*/
171+
public get activeDescendant (): string {
172+
return this.focusedItem ? this.focusedItem.id : null;
173+
}
174+
165175
/**
166176
* @hidden
167177
* @internal

projects/igniteui-angular/src/lib/drop-down/drop-down.component.spec.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,81 @@ describe('IgxDropDown ', () => {
10341034
});
10351035
});
10361036
describe('Rendering', () => {
1037+
describe('Accessibility', () => {
1038+
beforeEach(waitForAsync(() => {
1039+
TestBed.configureTestingModule({
1040+
imports: [
1041+
NoopAnimationsModule,
1042+
IgxDropDownTestComponent,
1043+
]
1044+
}).compileComponents();
1045+
}));
1046+
beforeEach(() => {
1047+
fixture = TestBed.createComponent(IgxDropDownTestComponent);
1048+
fixture.detectChanges();
1049+
dropdown = fixture.componentInstance.dropdown;
1050+
});
1051+
it('should set the aria-label property correctly', () => {
1052+
// Initially aria-label should be null
1053+
dropdown.toggle();
1054+
fixture.detectChanges();
1055+
let items = document.querySelectorAll(`.${CSS_CLASS_ITEM}`);
1056+
items.forEach(item => {
1057+
expect(item.getAttribute('aria-label')).toBeNull();
1058+
});
1059+
1060+
// Set value and check if aria-label reflects it
1061+
dropdown.toggle();
1062+
fixture.detectChanges();
1063+
dropdown.items.forEach((item, index) => item.value = `value ${index}`);
1064+
dropdown.toggle();
1065+
fixture.detectChanges();
1066+
items = document.querySelectorAll(`.${CSS_CLASS_ITEM}`);
1067+
items.forEach((item, index) => {
1068+
expect(item.getAttribute('aria-label')).toBe(`value ${index}`);
1069+
});
1070+
1071+
// Phase 3: Set explicit ariaLabel and verify it overrides value
1072+
dropdown.toggle();
1073+
fixture.detectChanges();
1074+
dropdown.items.forEach((item, index) => item.ariaLabel = `label ${index}`);
1075+
dropdown.toggle();
1076+
fixture.detectChanges();
1077+
items = document.querySelectorAll(`.${CSS_CLASS_ITEM}`);
1078+
items.forEach((item, index) => {
1079+
expect(item.getAttribute('aria-label')).toBe(`label ${index}`);
1080+
});
1081+
});
1082+
it('should update aria-activedescendant to the id of the focused item', fakeAsync(() => {
1083+
dropdown.toggle();
1084+
tick();
1085+
fixture.detectChanges();
1086+
1087+
const dropdownElement = fixture.debugElement.query(By.css(`.${CSS_CLASS_DROP_DOWN_BASE}`)).nativeElement;
1088+
let focusedItem = fixture.debugElement.query(By.css(`.${CSS_CLASS_FOCUSED}`)).nativeElement;
1089+
1090+
expect(focusedItem).toBeTruthy();
1091+
let focusedItemId = focusedItem.getAttribute('id');
1092+
expect(focusedItemId).toBeTruthy();
1093+
expect(dropdownElement.getAttribute('aria-activedescendant')).toBe(focusedItemId);
1094+
1095+
dropdown.toggle();
1096+
tick();
1097+
fixture.detectChanges();
1098+
dropdown.toggle();
1099+
tick();
1100+
fixture.detectChanges();
1101+
1102+
UIInteractions.triggerEventHandlerKeyDown('ArrowDown', fixture.debugElement.query(By.css(`.${CSS_CLASS_DROP_DOWN_BASE}`)));
1103+
tick();
1104+
fixture.detectChanges();
1105+
1106+
focusedItem = fixture.debugElement.query(By.css(`.${CSS_CLASS_FOCUSED}`)).nativeElement;
1107+
focusedItemId = focusedItem.getAttribute('id');
1108+
1109+
expect(dropdownElement.getAttribute('aria-activedescendant')).toBe(focusedItemId);
1110+
}));
1111+
});
10371112
describe('Grouped items', () => {
10381113
beforeEach(waitForAsync(() => {
10391114
TestBed.configureTestingModule({

src/app/drop-down/drop-down.sample.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
>
1717
@for(item of items; track item) {
1818
<igx-drop-down-item
19+
[ariaLabel]="item.field"
1920
[disabled]="item.disabled"
2021
[isHeader]="item.header"
2122
>

0 commit comments

Comments
 (0)