Skip to content

Commit

Permalink
fix(select): allow custom aria-label
Browse files Browse the repository at this point in the history
* Adds support for custom `aria-label` attributes on the select host element.
* Also fixes that the `aria-labelledby` attribute is overwritten by the placeholder `aria-label`.

Fixes angular#3762.
  • Loading branch information
devversion committed Mar 24, 2017
1 parent a25e7bb commit 1be81eb
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
19 changes: 18 additions & 1 deletion src/lib/select/select.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,21 @@ describe('MdSelect', () => {
expect(select.getAttribute('aria-label')).toEqual('Food');
});

it('should support setting a custom aria-label', () => {
fixture.componentInstance.ariaLabel = 'Custom Label';
fixture.detectChanges();

expect(select.getAttribute('aria-label')).toEqual('Custom Label');
});

it('should not set a aria-label if aria-labelledby is specified', () => {
fixture.componentInstance.ariaLabelledby = 'myLabelId';
fixture.detectChanges();

expect(select.getAttribute('aria-label')).toBeFalsy('Expected no aria-label to be set.');
expect(select.getAttribute('aria-labelledby')).toBe('myLabelId');
});

it('should set the tabindex of the select to 0 by default', () => {
expect(select.getAttribute('tabindex')).toEqual('0');
});
Expand Down Expand Up @@ -1606,7 +1621,7 @@ describe('MdSelect', () => {
template: `
<div [style.height.px]="heightAbove"></div>
<md-select placeholder="Food" [formControl]="control" [required]="isRequired"
[tabIndex]="tabIndexOverride">
[tabIndex]="tabIndexOverride" [aria-label]="ariaLabel" [aria-labelledby]="ariaLabelledby">
<md-option *ngFor="let food of foods" [value]="food.value" [disabled]="food.disabled">
{{ food.viewValue }}
</md-option>
Expand All @@ -1630,6 +1645,8 @@ class BasicSelect {
heightAbove = 0;
heightBelow = 0;
tabIndexOverride: number;
ariaLabel: string;
ariaLabelledby: string;

@ViewChild(MdSelect) select: MdSelect;
@ViewChildren(MdOption) options: QueryList<MdOption>;
Expand Down
16 changes: 15 additions & 1 deletion src/lib/select/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export type MdSelectFloatPlaceholderType = 'always' | 'never' | 'auto';
host: {
'role': 'listbox',
'[attr.tabindex]': 'tabIndex',
'[attr.aria-label]': 'placeholder',
'[attr.aria-label]': '_ariaLabel',
'[attr.aria-labelledby]': 'ariaLabelledby',
'[attr.aria-required]': 'required.toString()',
'[attr.aria-disabled]': 'disabled.toString()',
'[attr.aria-invalid]': '_control?.invalid || "false"',
Expand Down Expand Up @@ -279,6 +280,12 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
}
}

/** Aria label of the select. If not specified, the placeholder will be used as label. */
@Input('aria-label') ariaLabel: string = '';

/** Input that can be used to specify the `aria-labelledby` attribute. */
@Input('aria-labelledby') ariaLabelledby: string = '';

/** Combined stream of all of the child options' change events. */
get optionSelectionChanges(): Observable<MdOptionSelectionChange> {
return Observable.merge(...this.options.map(option => option.onSelectionChange));
Expand Down Expand Up @@ -747,6 +754,13 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
'visible' : 'hidden';
}

/** Returns the aria-label of the select component. */
get _ariaLabel(): string {
// If a ariaLabelledby value has been set, the select should not overwrite the
// `aria-labelledby` value by setting the ariaLabel to the placeholder.
return this.ariaLabelledby ? null : this.ariaLabel || this.placeholder;
}

/**
* Calculates the y-offset of the select's overlay panel in relation to the
* top start corner of the trigger. It has to be adjusted in order for the
Expand Down

0 comments on commit 1be81eb

Please sign in to comment.