diff --git a/src/examples/example-module.ts b/src/examples/example-module.ts
index 60293aeb56ff..f6a06509c251 100644
--- a/src/examples/example-module.ts
+++ b/src/examples/example-module.ts
@@ -66,6 +66,7 @@ import {TabsTemplateLabelExample} from './tabs-template-label/tabs-template-labe
import {RadioOverviewExample} from './radio-overview/radio-overview-example';
import {SidenavOverviewExample} from './sidenav-overview/sidenav-overview-example';
import {SelectOverviewExample} from './select-overview/select-overview-example';
+import {SelectLabelExample} from './select-label/select-label-example';
import {ChipsOverviewExample} from './chips-overview/chips-overview-example';
import {ChipsStackedExample} from './chips-stacked/chips-stacked-example';
import {SelectFormExample} from './select-form/select-form-example';
@@ -141,6 +142,7 @@ export const EXAMPLE_COMPONENTS = {
'radio-ng-model': {title: 'Radios with ngModel', component: RadioNgModelExample},
'radio-overview': {title: 'Basic radios', component: RadioOverviewExample},
'select-overview': {title: 'Basic select', component: SelectOverviewExample},
+ 'select-label': {title: 'Select with custom label', component: SelectLabelExample},
'select-form': {title: 'Select in a form', component: SelectFormExample},
'sidenav-fab': {title: 'Sidenav with a FAB', component: SidenavFabExample},
'sidenav-overview': {title: 'Basic sidenav', component: SidenavOverviewExample},
@@ -203,6 +205,7 @@ export const EXAMPLE_LIST = [
RadioOverviewExample,
SidenavFabExample,
SelectOverviewExample,
+ SelectLabelExample,
SelectFormExample,
SidenavOverviewExample,
SliderConfigurableExample,
diff --git a/src/examples/select-label/select-label-example.css b/src/examples/select-label/select-label-example.css
new file mode 100644
index 000000000000..7432308753e6
--- /dev/null
+++ b/src/examples/select-label/select-label-example.css
@@ -0,0 +1 @@
+/** No CSS for this example */
diff --git a/src/examples/select-label/select-label-example.html b/src/examples/select-label/select-label-example.html
new file mode 100644
index 000000000000..6bf6c39a4237
--- /dev/null
+++ b/src/examples/select-label/select-label-example.html
@@ -0,0 +1,6 @@
+
+ You have selected: {{ select.selected?.viewValue }}
+
+ {{ food.viewValue }}
+
+
diff --git a/src/examples/select-label/select-label-example.ts b/src/examples/select-label/select-label-example.ts
new file mode 100644
index 000000000000..fc35a273a84e
--- /dev/null
+++ b/src/examples/select-label/select-label-example.ts
@@ -0,0 +1,14 @@
+import {Component} from '@angular/core';
+
+
+@Component({
+ selector: 'select-label-example',
+ templateUrl: './select-label-example.html',
+})
+export class SelectLabelExample {
+ foods = [
+ {value: 'steak-0', viewValue: 'Steak'},
+ {value: 'pizza-1', viewValue: 'Pizza'},
+ {value: 'tacos-2', viewValue: 'Tacos'}
+ ];
+}
diff --git a/src/lib/select/index.ts b/src/lib/select/index.ts
index 1a2e4afe6a88..0a76d2ddf482 100644
--- a/src/lib/select/index.ts
+++ b/src/lib/select/index.ts
@@ -1,19 +1,21 @@
import {NgModule, ModuleWithProviders} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MdSelect} from './select';
+import {MdSelectLabel} from './select-label';
import {MdOptionModule} from '../core/option/option';
import {
CompatibilityModule,
OverlayModule,
} from '../core';
export * from './select';
+export * from './select-label';
export {fadeInContent, transformPanel, transformPlaceholder} from './select-animations';
@NgModule({
imports: [CommonModule, OverlayModule, MdOptionModule, CompatibilityModule],
- exports: [MdSelect, MdOptionModule, CompatibilityModule],
- declarations: [MdSelect],
+ exports: [MdSelect, MdSelectLabel, MdOptionModule, CompatibilityModule],
+ declarations: [MdSelect, MdSelectLabel],
})
export class MdSelectModule {
/** @deprecated */
diff --git a/src/lib/select/select-label.ts b/src/lib/select/select-label.ts
new file mode 100644
index 000000000000..79cbcbd8f5f6
--- /dev/null
+++ b/src/lib/select/select-label.ts
@@ -0,0 +1,9 @@
+import {Directive} from '@angular/core';
+
+/**
+ * Allows the user to customize the label that is displayed `md-select` has a value.
+ */
+@Directive({
+ selector: 'md-select-label, mat-select-label'
+})
+export class MdSelectLabel { }
diff --git a/src/lib/select/select.html b/src/lib/select/select.html
index d3ae2a6ca256..953106d35f72 100644
--- a/src/lib/select/select.html
+++ b/src/lib/select/select.html
@@ -6,7 +6,10 @@
[style.visibility]="_getPlaceholderVisibility()"
[style.width.px]="_selectedValueWidth"> {{ placeholder }}
- {{ selected?.viewValue }}
+
+
+ {{ selected?.viewValue }}
+
diff --git a/src/lib/select/select.spec.ts b/src/lib/select/select.spec.ts
index 63e1f8f848f6..e83c1ec17318 100644
--- a/src/lib/select/select.spec.ts
+++ b/src/lib/select/select.spec.ts
@@ -39,7 +39,8 @@ describe('MdSelect', () => {
FloatPlaceholderSelect,
SelectWithErrorSibling,
ThrowsErrorOnInit,
- BasicSelectOnPush
+ BasicSelectOnPush,
+ SelectWithCustomLabel
],
providers: [
{provide: OverlayContainer, useFactory: () => {
@@ -579,7 +580,6 @@ describe('MdSelect', () => {
});
-
describe('animations', () => {
let fixture: ComponentFixture;
let trigger: HTMLElement;
@@ -1253,6 +1253,19 @@ describe('MdSelect', () => {
}).toThrowError(new RegExp('Oh no!', 'g'));
}));
+ it('should allow the user to customize the label', () => {
+ const fixture = TestBed.createComponent(SelectWithCustomLabel);
+ fixture.detectChanges();
+
+ fixture.componentInstance.control.setValue('pizza-1');
+ fixture.detectChanges();
+
+ const label = fixture.debugElement.query(By.css('.mat-select-value')).nativeElement;
+
+ expect(label.textContent).toContain('azziP',
+ 'Expected the displayed text to be "Pizza" in reverse.');
+ });
+
});
describe('change event', () => {
@@ -1343,6 +1356,7 @@ describe('MdSelect', () => {
expect(trigger.textContent).not.toContain('Pizza');
});
});
+
});
@@ -1589,6 +1603,26 @@ class FloatPlaceholderSelect {
@ViewChild(MdSelect) select: MdSelect;
}
+@Component({
+ selector: 'select-with-custom-label',
+ template: `
+
+
+ {{ select.selected?.viewValue.split('').reverse().join('') }}
+
+
+ {{ food.viewValue }}
+
+
+ `
+})
+class SelectWithCustomLabel {
+ foods: any[] = [
+ { value: 'steak-0', viewValue: 'Steak' },
+ { value: 'pizza-1', viewValue: 'Pizza' },
+ ];
+ control = new FormControl();
+}
class FakeViewportRuler {
getViewportRect() {
diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts
index 1a92699e5437..c476fafc1381 100644
--- a/src/lib/select/select.ts
+++ b/src/lib/select/select.ts
@@ -1,6 +1,7 @@
import {
AfterContentInit,
Component,
+ ContentChild,
ContentChildren,
ElementRef,
EventEmitter,
@@ -25,6 +26,7 @@ import {ControlValueAccessor, NgControl} from '@angular/forms';
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
import {ConnectedOverlayDirective} from '../core/overlay/overlay-directives';
import {ViewportRuler} from '../core/overlay/position/viewport-ruler';
+import {MdSelectLabel} from './select-label';
import 'rxjs/add/operator/startWith';
@@ -207,6 +209,9 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
/** All of the defined select options. */
@ContentChildren(MdOption) options: QueryList;
+ /** User-supplied override of the selected value label. */
+ @ContentChild(MdSelectLabel) customLabel: MdSelectLabel;
+
/** Placeholder to be shown if no value has been selected. */
@Input()
get placeholder() { return this._placeholder; }