Skip to content

Commit 1504b3d

Browse files
committed
fix(chips): allow for role to be overwritten on chip list and chip
Allows for the ARIA `role` of the `mat-chip-list` and `mat-chip` to be overwritten. Fixes #15787.
1 parent 948dfa9 commit 1504b3d

File tree

5 files changed

+53
-7
lines changed

5 files changed

+53
-7
lines changed

src/material/chips/chip-list.spec.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ describe('MatChipList', () => {
170170
expect(chipListNativeElement.hasAttribute('role')).toBe(false);
171171
expect(chipListNativeElement.hasAttribute('aria-required')).toBe(false);
172172
});
173+
174+
it('should be able to set a custom role', () => {
175+
fixture.componentInstance.chipList.role = 'grid';
176+
fixture.detectChanges();
177+
178+
expect(chipListNativeElement.getAttribute('role')).toBe('grid');
179+
});
173180
});
174181

175182
describe('focus behaviors', () => {
@@ -1583,9 +1590,9 @@ class FalsyValueChipList {
15831590
@Component({
15841591
template: `
15851592
<mat-chip-list>
1586-
<mat-chip *ngFor="let food of foods" [value]="food.value" [selected]="food.selected">
1587-
{{ food.viewValue }}
1588-
</mat-chip>
1593+
<mat-chip *ngFor="let food of foods" [value]="food.value" [selected]="food.selected">
1594+
{{ food.viewValue }}
1595+
</mat-chip>
15891596
</mat-chip-list>
15901597
`
15911598
})
@@ -1596,6 +1603,7 @@ class SelectedChipList {
15961603
{value: 2, viewValue: 'Pasta', selected: true},
15971604
];
15981605
@ViewChildren(MatChip) chips: QueryList<MatChip>;
1606+
@ViewChild(MatChipList, {static: false}) chipList: MatChipList;
15991607
}
16001608

16011609
@Component({

src/material/chips/chip-list.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,18 @@ export class MatChipList extends _MatChipListMixinBase implements MatFormFieldCo
164164
}
165165

166166
/** The ARIA role applied to the chip list. */
167-
get role(): string | null { return this.empty ? null : 'listbox'; }
167+
@Input()
168+
get role(): string | null {
169+
if (this._explicitRole) {
170+
return this._explicitRole;
171+
}
172+
173+
return this.empty ? null : 'listbox';
174+
}
175+
set role(role: string | null) {
176+
this._explicitRole = role;
177+
}
178+
private _explicitRole?: string | null;
168179

169180
/** An object used to control when error messages are shown. */
170181
@Input() errorStateMatcher: ErrorStateMatcher;

src/material/chips/chip.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,28 @@ describe('MatChip', () => {
6969

7070
expect(chip.getAttribute('tabindex')).toBe('15');
7171
});
72+
73+
it('should have the correct role', () => {
74+
fixture = TestBed.createComponent(BasicChip);
75+
fixture.detectChanges();
76+
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
77+
chipNativeElement = chipDebugElement.nativeElement;
78+
79+
expect(chipNativeElement.getAttribute('role')).toBe('option');
80+
});
81+
82+
it('should be able to set a custom role', () => {
83+
fixture = TestBed.createComponent(BasicChip);
84+
fixture.detectChanges();
85+
chipDebugElement = fixture.debugElement.query(By.directive(MatChip))!;
86+
chipInstance = chipDebugElement.injector.get<MatChip>(MatChip);
87+
chipNativeElement = chipDebugElement.nativeElement;
88+
89+
chipInstance.role = 'gridcell';
90+
fixture.detectChanges();
91+
92+
expect(chipNativeElement.getAttribute('role')).toBe('gridcell');
93+
});
7294
});
7395

7496

src/material/chips/chip.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export class MatChipTrailingIcon {}
106106
host: {
107107
'class': 'mat-chip mat-focus-indicator',
108108
'[attr.tabindex]': 'disabled ? null : tabIndex',
109-
'role': 'option',
109+
'[attr.role]': 'role',
110110
'[class.mat-chip-selected]': 'selected',
111111
'[class.mat-chip-with-avatar]': 'avatar',
112112
'[class.mat-chip-with-trailing-icon]': 'trailingIcon || removeIcon',
@@ -174,6 +174,9 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
174174
/** The chip's remove toggler. */
175175
@ContentChild(forwardRef(() => MatChipRemove)) removeIcon: MatChipRemove;
176176

177+
/** ARIA role that should be applied to the chip. */
178+
@Input() role: string = 'option';
179+
177180
/** Whether the chip is selected. */
178181
@Input()
179182
get selected(): boolean { return this._selected; }

tools/public_api_guard/material/chips.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export declare class MatChip extends _MatChipMixinBase implements FocusableOptio
2525
readonly removed: EventEmitter<MatChipEvent>;
2626
rippleConfig: RippleConfig & RippleGlobalOptions;
2727
get rippleDisabled(): boolean;
28+
role: string;
2829
get selectable(): boolean;
2930
set selectable(value: boolean);
3031
get selected(): boolean;
@@ -50,7 +51,7 @@ export declare class MatChip extends _MatChipMixinBase implements FocusableOptio
5051
static ngAcceptInputType_removable: BooleanInput;
5152
static ngAcceptInputType_selectable: BooleanInput;
5253
static ngAcceptInputType_selected: BooleanInput;
53-
static ɵdir: i0.ɵɵDirectiveDefWithMeta<MatChip, "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", ["matChip"], { "color": "color"; "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; "selected": "selected"; "value": "value"; "selectable": "selectable"; "disabled": "disabled"; "removable": "removable"; }, { "selectionChange": "selectionChange"; "destroyed": "destroyed"; "removed": "removed"; }, ["avatar", "trailingIcon", "removeIcon"]>;
54+
static ɵdir: i0.ɵɵDirectiveDefWithMeta<MatChip, "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", ["matChip"], { "color": "color"; "disableRipple": "disableRipple"; "tabIndex": "tabIndex"; "role": "role"; "selected": "selected"; "value": "value"; "selectable": "selectable"; "disabled": "disabled"; "removable": "removable"; }, { "selectionChange": "selectionChange"; "destroyed": "destroyed"; "removed": "removed"; }, ["avatar", "trailingIcon", "removeIcon"]>;
5455
static ɵfac: i0.ɵɵFactoryDef<MatChip, [null, null, null, { optional: true; }, { optional: true; }, null, { attribute: "tabindex"; }, { optional: true; }]>;
5556
}
5657

@@ -138,6 +139,7 @@ export declare class MatChipList extends _MatChipListMixinBase implements MatFor
138139
get required(): boolean;
139140
set required(value: boolean);
140141
get role(): string | null;
142+
set role(role: string | null);
141143
get selectable(): boolean;
142144
set selectable(value: boolean);
143145
get selected(): MatChip[] | MatChip;
@@ -172,7 +174,7 @@ export declare class MatChipList extends _MatChipListMixinBase implements MatFor
172174
static ngAcceptInputType_multiple: BooleanInput;
173175
static ngAcceptInputType_required: BooleanInput;
174176
static ngAcceptInputType_selectable: BooleanInput;
175-
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatChipList, "mat-chip-list", ["matChipList"], { "errorStateMatcher": "errorStateMatcher"; "multiple": "multiple"; "compareWith": "compareWith"; "value": "value"; "required": "required"; "placeholder": "placeholder"; "disabled": "disabled"; "ariaOrientation": "aria-orientation"; "selectable": "selectable"; "tabIndex": "tabIndex"; }, { "change": "change"; "valueChange": "valueChange"; }, ["chips"], ["*"]>;
177+
static ɵcmp: i0.ɵɵComponentDefWithMeta<MatChipList, "mat-chip-list", ["matChipList"], { "role": "role"; "errorStateMatcher": "errorStateMatcher"; "multiple": "multiple"; "compareWith": "compareWith"; "value": "value"; "required": "required"; "placeholder": "placeholder"; "disabled": "disabled"; "ariaOrientation": "aria-orientation"; "selectable": "selectable"; "tabIndex": "tabIndex"; }, { "change": "change"; "valueChange": "valueChange"; }, ["chips"], ["*"]>;
176178
static ɵfac: i0.ɵɵFactoryDef<MatChipList, [null, null, { optional: true; }, { optional: true; }, { optional: true; }, null, { optional: true; self: true; }]>;
177179
}
178180

0 commit comments

Comments
 (0)