Skip to content

Commit

Permalink
feat(select): add ability to customize the select trigger
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 angular#2275.
  • Loading branch information
crisbeto committed Aug 8, 2017
1 parent a190de7 commit e3cdb21
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 e3cdb21

Please sign in to comment.