Skip to content

Commit e3cdb21

Browse files
committed
feat(select): add ability to customize the select trigger
Adds the `md-select-trigger` directive which allows users to customize the selected value. E.g. it is now possible to do something like this, if the user wanted to reverse the selected label for some reason: ```ts <md-select placeholder="Food" [formControl]="control" #select="mdSelect"> <md-select-trigger> {{ select.selected?.viewValue.split('').reverse().join('') }} </md-select-trigger> <md-option *ngFor="let food of foods" [value]="food.value"> {{ food.viewValue }} </md-option> </md-select> ``` Fixes #2275.
1 parent a190de7 commit e3cdb21

File tree

5 files changed

+71
-6
lines changed

5 files changed

+71
-6
lines changed

src/lib/select/index.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {NgModule} from '@angular/core';
1010
import {CommonModule} from '@angular/common';
11-
import {MdSelect, MD_SELECT_SCROLL_STRATEGY_PROVIDER} from './select';
11+
import {MdSelect, MdSelectTrigger, MD_SELECT_SCROLL_STRATEGY_PROVIDER} from './select';
1212
import {MdCommonModule, OverlayModule, MdOptionModule} from '../core';
1313

1414

@@ -19,8 +19,8 @@ import {MdCommonModule, OverlayModule, MdOptionModule} from '../core';
1919
MdOptionModule,
2020
MdCommonModule,
2121
],
22-
exports: [MdSelect, MdOptionModule, MdCommonModule],
23-
declarations: [MdSelect],
22+
exports: [MdSelect, MdSelectTrigger, MdOptionModule, MdCommonModule],
23+
declarations: [MdSelect, MdSelectTrigger],
2424
providers: [MD_SELECT_SCROLL_STRATEGY_PROVIDER]
2525
})
2626
export class MdSelectModule {}

src/lib/select/select.html

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
[@transformPlaceholder]="_getPlaceholderAnimationState()"
1212
[style.opacity]="_getPlaceholderOpacity()"
1313
[style.width.px]="_selectedValueWidth"> {{ placeholder }} </span>
14+
1415
<span class="mat-select-value" *ngIf="_hasValue()">
15-
<span class="mat-select-value-text">{{ triggerValue }}</span>
16+
<span class="mat-select-value-text" [ngSwitch]="!!customTrigger">
17+
<span *ngSwitchDefault>{{ triggerValue }}</span>
18+
<ng-content select="md-select-trigger, mat-select-trigger" *ngSwitchCase="true"></ng-content>
19+
</span>
1620
</span>
1721

1822
<span class="mat-select-arrow"></span>

src/lib/select/select.md

+10
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ Global default placeholder options can be specified by setting the `MD_PLACEHOLD
7272
})
7373
```
7474

75+
### Customizing the trigger label
76+
If you want to display a custom trigger label inside a select, you can use the `md-select-trigger` element:
77+
78+
```html
79+
<md-select placeholder="Favorite food" #select="mdSelect">
80+
<md-select-trigger>You have selected: {{ select.selected?.viewValue }}</md-select-trigger>
81+
<md-option *ngFor="let food of foods" [value]="food.value">{{ food.viewValue }}</md-option>
82+
</md-select>
83+
```
84+
7585
Here are the available global options:
7686

7787
| Name | Type | Values | Description |

src/lib/select/select.spec.ts

+38-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ describe('MdSelect', () => {
7474
BasicSelectWithoutForms,
7575
BasicSelectWithoutFormsPreselected,
7676
BasicSelectWithoutFormsMultiple,
77-
SelectInsideFormGroup
77+
SelectInsideFormGroup,
78+
SelectWithCustomTrigger
7879
],
7980
providers: [
8081
{provide: OverlayContainer, useFactory: () => {
@@ -951,7 +952,6 @@ describe('MdSelect', () => {
951952

952953
});
953954

954-
955955
describe('animations', () => {
956956
let fixture: ComponentFixture<BasicSelect>;
957957
let trigger: HTMLElement;
@@ -2529,6 +2529,21 @@ describe('MdSelect', () => {
25292529
expect(panel.classList).toContain('mat-warn');
25302530
});
25312531

2532+
it('should allow the user to customize the label', () => {
2533+
fixture.destroy();
2534+
2535+
const labelFixture = TestBed.createComponent(SelectWithCustomTrigger);
2536+
labelFixture.detectChanges();
2537+
2538+
labelFixture.componentInstance.control.setValue('pizza-1');
2539+
labelFixture.detectChanges();
2540+
2541+
const label = labelFixture.debugElement.query(By.css('.mat-select-value')).nativeElement;
2542+
2543+
expect(label.textContent).toContain('azziP',
2544+
'Expected the displayed text to be "Pizza" in reverse.');
2545+
});
2546+
25322547
});
25332548

25342549
describe('reset values', () => {
@@ -3212,3 +3227,24 @@ class BasicSelectWithoutFormsMultiple {
32123227

32133228
@ViewChild(MdSelect) select: MdSelect;
32143229
}
3230+
3231+
@Component({
3232+
selector: 'select-with-custom-trigger',
3233+
template: `
3234+
<md-select placeholder="Food" [formControl]="control" #select="mdSelect">
3235+
<md-select-trigger>
3236+
{{ select.selected?.viewValue.split('').reverse().join('') }}
3237+
</md-select-trigger>
3238+
<md-option *ngFor="let food of foods" [value]="food.value">
3239+
{{ food.viewValue }}
3240+
</md-option>
3241+
</md-select>
3242+
`
3243+
})
3244+
class SelectWithCustomTrigger {
3245+
foods: any[] = [
3246+
{ value: 'steak-0', viewValue: 'Steak' },
3247+
{ value: 'pizza-1', viewValue: 'Pizza' },
3248+
];
3249+
control = new FormControl();
3250+
}

src/lib/select/select.ts

+15
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import {
1010
AfterContentInit,
1111
Component,
12+
ContentChild,
1213
ContentChildren,
1314
ElementRef,
1415
EventEmitter,
@@ -27,6 +28,7 @@ import {
2728
Inject,
2829
ChangeDetectionStrategy,
2930
InjectionToken,
31+
Directive,
3032
} from '@angular/core';
3133
import {NgForm, FormGroupDirective} from '@angular/forms';
3234
import {MdOption, MdOptionSelectionChange, MdOptgroup} from '../core/option/index';
@@ -147,6 +149,16 @@ export class MdSelectBase {
147149
}
148150
export const _MdSelectMixinBase = mixinColor(mixinDisabled(MdSelectBase), 'primary');
149151

152+
153+
/**
154+
* Allows the user to customize the trigger that is displayed when the select has a value.
155+
*/
156+
@Directive({
157+
selector: 'md-select-trigger, mat-select-trigger'
158+
})
159+
export class MdSelectTrigger {}
160+
161+
150162
@Component({
151163
moduleId: module.id,
152164
selector: 'md-select, mat-select',
@@ -293,6 +305,9 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
293305
/** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */
294306
@Input() panelClass: string|string[]|Set<string>|{[key: string]: any};
295307

308+
/** User-supplied override of the trigger element. */
309+
@ContentChild(MdSelectTrigger) customTrigger: MdSelectTrigger;
310+
296311
/** Placeholder to be shown if no value has been selected. */
297312
@Input()
298313
get placeholder() { return this._placeholder; }

0 commit comments

Comments
 (0)