From 72c5d39fc3a023c54ceb324395b4bb2ca8a39373 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 9 Aug 2017 23:59:08 +0200 Subject: [PATCH] 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 {{ select.selected?.viewValue.split('').reverse().join('') }} {{ food.viewValue }} ``` Fixes #2275. --- src/lib/select/index.ts | 6 +++--- src/lib/select/select.html | 6 +++++- src/lib/select/select.md | 10 +++++++++ src/lib/select/select.spec.ts | 40 +++++++++++++++++++++++++++++++++-- src/lib/select/select.ts | 15 +++++++++++++ 5 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/lib/select/index.ts b/src/lib/select/index.ts index bf5f903905fb..83fcb32d6747 100644 --- a/src/lib/select/index.ts +++ b/src/lib/select/index.ts @@ -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 {} diff --git a/src/lib/select/select.html b/src/lib/select/select.html index 250d37f2079e..86a090bcca31 100644 --- a/src/lib/select/select.html +++ b/src/lib/select/select.html @@ -11,8 +11,12 @@ [@transformPlaceholder]="_getPlaceholderAnimationState()" [style.opacity]="_getPlaceholderOpacity()" [style.width.px]="_selectedValueWidth"> {{ placeholder }} + - {{ triggerValue }} + + {{ triggerValue }} + + diff --git a/src/lib/select/select.md b/src/lib/select/select.md index 4e683475ebda..46f60b95a22f 100644 --- a/src/lib/select/select.md +++ b/src/lib/select/select.md @@ -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 + + You have selected: {{ select.selected?.viewValue }} + {{ food.viewValue }} + +``` + Here are the available global options: | Name | Type | Values | Description | diff --git a/src/lib/select/select.spec.ts b/src/lib/select/select.spec.ts index b34f502d9f71..6f7e382e2a58 100644 --- a/src/lib/select/select.spec.ts +++ b/src/lib/select/select.spec.ts @@ -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; 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: ` + + + {{ select.selected?.viewValue.split('').reverse().join('') }} + + + {{ food.viewValue }} + + + ` +}) +class SelectWithCustomTrigger { + foods: any[] = [ + { value: 'steak-0', viewValue: 'Steak' }, + { value: 'pizza-1', viewValue: 'Pizza' }, + ]; + control = new FormControl(); +} diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts index 6483c60c11ca..3887896a69a8 100644 --- a/src/lib/select/select.ts +++ b/src/lib/select/select.ts @@ -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|{[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; }