Skip to content

Commit

Permalink
feat(select): add ability to customize the select trigger (#3341)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto authored and mmalerba committed Aug 9, 2017
1 parent 2286ad5 commit 72c5d39
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 6 deletions.
6 changes: 3 additions & 3 deletions src/lib/select/index.ts
Expand Up @@ -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';


Expand All @@ -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 {}
Expand Down
6 changes: 5 additions & 1 deletion src/lib/select/select.html
Expand Up @@ -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>
Expand Down
10 changes: 10 additions & 0 deletions src/lib/select/select.md
Expand Up @@ -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 |
Expand Down
40 changes: 38 additions & 2 deletions src/lib/select/select.spec.ts
Expand Up @@ -74,7 +74,8 @@ describe('MdSelect', () => {
BasicSelectWithoutForms,
BasicSelectWithoutFormsPreselected,
BasicSelectWithoutFormsMultiple,
SelectInsideFormGroup
SelectInsideFormGroup,
SelectWithCustomTrigger
],
providers: [
{provide: OverlayContainer, useFactory: () => {
Expand Down Expand Up @@ -951,7 +952,6 @@ describe('MdSelect', () => {

});


describe('animations', () => {
let fixture: ComponentFixture<BasicSelect>;
let trigger: HTMLElement;
Expand Down Expand Up @@ -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', () => {
Expand Down Expand Up @@ -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 changes: 15 additions & 0 deletions src/lib/select/select.ts
Expand Up @@ -9,6 +9,7 @@
import {
AfterContentInit,
Component,
ContentChild,
ContentChildren,
ElementRef,
EventEmitter,
Expand All @@ -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';
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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; }
Expand Down

0 comments on commit 72c5d39

Please sign in to comment.