feat(select): add ability to customize the select trigger (#3341)

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.
This commit is contained in:
Kristiyan Kostadinov
2017-08-09 23:59:08 +02:00
committed by mmalerba
parent 2286ad5b98
commit 72c5d39fc3
5 changed files with 71 additions and 6 deletions
+3 -3
View File
@@ -8,7 +8,7 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MdSelect, MD_SELECT_SCROLL_STRATEGY_PROVIDER} from './select';
import {MdSelect, MdSelectTrigger, MD_SELECT_SCROLL_STRATEGY_PROVIDER} from './select';
import {MdCommonModule, OverlayModule, MdOptionModule} from '../core';
@@ -19,8 +19,8 @@ import {MdCommonModule, OverlayModule, MdOptionModule} from '../core';
MdOptionModule,
MdCommonModule,
],
exports: [MdSelect, MdOptionModule, MdCommonModule],
declarations: [MdSelect],
exports: [MdSelect, MdSelectTrigger, MdOptionModule, MdCommonModule],
declarations: [MdSelect, MdSelectTrigger],
providers: [MD_SELECT_SCROLL_STRATEGY_PROVIDER]
})
export class MdSelectModule {}
+5 -1
View File
@@ -11,8 +11,12 @@
[@transformPlaceholder]="_getPlaceholderAnimationState()"
[style.opacity]="_getPlaceholderOpacity()"
[style.width.px]="_selectedValueWidth"> {{ placeholder }} </span>
<span class="mat-select-value" *ngIf="_hasValue()">
<span class="mat-select-value-text">{{ triggerValue }}</span>
<span class="mat-select-value-text" [ngSwitch]="!!customTrigger">
<span *ngSwitchDefault>{{ triggerValue }}</span>
<ng-content select="md-select-trigger, mat-select-trigger" *ngSwitchCase="true"></ng-content>
</span>
</span>
<span class="mat-select-arrow"></span>
+10
View File
@@ -72,6 +72,16 @@ Global default placeholder options can be specified by setting the `MD_PLACEHOLD
})
```
### Customizing the trigger label
If you want to display a custom trigger label inside a select, you can use the `md-select-trigger` element:
```html
<md-select placeholder="Favorite food" #select="mdSelect">
<md-select-trigger>You have selected: {{ select.selected?.viewValue }}</md-select-trigger>
<md-option *ngFor="let food of foods" [value]="food.value">{{ food.viewValue }}</md-option>
</md-select>
```
Here are the available global options:
| Name | Type | Values | Description |
+38 -2
View File
@@ -74,7 +74,8 @@ describe('MdSelect', () => {
BasicSelectWithoutForms,
BasicSelectWithoutFormsPreselected,
BasicSelectWithoutFormsMultiple,
SelectInsideFormGroup
SelectInsideFormGroup,
SelectWithCustomTrigger
],
providers: [
{provide: OverlayContainer, useFactory: () => {
@@ -951,7 +952,6 @@ describe('MdSelect', () => {
});
describe('animations', () => {
let fixture: ComponentFixture<BasicSelect>;
let trigger: HTMLElement;
@@ -2529,6 +2529,21 @@ describe('MdSelect', () => {
expect(panel.classList).toContain('mat-warn');
});
it('should allow the user to customize the label', () => {
fixture.destroy();
const labelFixture = TestBed.createComponent(SelectWithCustomTrigger);
labelFixture.detectChanges();
labelFixture.componentInstance.control.setValue('pizza-1');
labelFixture.detectChanges();
const label = labelFixture.debugElement.query(By.css('.mat-select-value')).nativeElement;
expect(label.textContent).toContain('azziP',
'Expected the displayed text to be "Pizza" in reverse.');
});
});
describe('reset values', () => {
@@ -3212,3 +3227,24 @@ class BasicSelectWithoutFormsMultiple {
@ViewChild(MdSelect) select: MdSelect;
}
@Component({
selector: 'select-with-custom-trigger',
template: `
<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>
`
})
class SelectWithCustomTrigger {
foods: any[] = [
{ value: 'steak-0', viewValue: 'Steak' },
{ value: 'pizza-1', viewValue: 'Pizza' },
];
control = new FormControl();
}
+15
View File
@@ -9,6 +9,7 @@
import {
AfterContentInit,
Component,
ContentChild,
ContentChildren,
ElementRef,
EventEmitter,
@@ -27,6 +28,7 @@ import {
Inject,
ChangeDetectionStrategy,
InjectionToken,
Directive,
} from '@angular/core';
import {NgForm, FormGroupDirective} from '@angular/forms';
import {MdOption, MdOptionSelectionChange, MdOptgroup} from '../core/option/index';
@@ -147,6 +149,16 @@ export class MdSelectBase {
}
export const _MdSelectMixinBase = mixinColor(mixinDisabled(MdSelectBase), 'primary');
/**
* Allows the user to customize the trigger that is displayed when the select has a value.
*/
@Directive({
selector: 'md-select-trigger, mat-select-trigger'
})
export class MdSelectTrigger {}
@Component({
moduleId: module.id,
selector: 'md-select, mat-select',
@@ -293,6 +305,9 @@ export class MdSelect extends _MdSelectMixinBase implements AfterContentInit, On
/** Classes to be passed to the select panel. Supports the same syntax as `ngClass`. */
@Input() panelClass: string|string[]|Set<string>|{[key: string]: any};
/** User-supplied override of the trigger element. */
@ContentChild(MdSelectTrigger) customTrigger: MdSelectTrigger;
/** Placeholder to be shown if no value has been selected. */
@Input()
get placeholder() { return this._placeholder; }