+
@@ -30,6 +31,7 @@
+
diff --git a/src/lib/select/select.spec.ts b/src/lib/select/select.spec.ts
index d93404c6733e..cd973859983d 100644
--- a/src/lib/select/select.spec.ts
+++ b/src/lib/select/select.spec.ts
@@ -193,19 +193,19 @@ describe('MdSelect', () => {
});
it('should focus the selected option if an option is selected', async(() => {
- trigger.click();
- fixture.detectChanges();
-
- const options =
- overlayContainerElement.querySelectorAll('md-option') as NodeListOf;
- options[1].click();
- fixture.detectChanges();
+ // must wait for initial writeValue promise to finish
+ fixture.whenStable().then(() => {
+ fixture.componentInstance.control.setValue('pizza-1');
+ fixture.detectChanges();
- trigger.click();
- fixture.detectChanges();
+ trigger.click();
+ fixture.detectChanges();
- fixture.whenStable().then(() => {
- expect(fixture.componentInstance.select._keyManager.focusedItemIndex).toEqual(1);
+ // must wait for animation to finish
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ expect(fixture.componentInstance.select._keyManager.focusedItemIndex).toEqual(1);
+ });
});
}));
@@ -307,6 +307,49 @@ describe('MdSelect', () => {
.toEqual('steak-0', `Expected control's value to be set to the new option.`);
});
+ it('should clear the selection when a nonexistent option value is selected', () => {
+ fixture.componentInstance.control.setValue('pizza-1');
+ fixture.detectChanges();
+
+ fixture.componentInstance.control.setValue('gibberish');
+ fixture.detectChanges();
+
+ const value = fixture.debugElement.query(By.css('.md-select-value'));
+ expect(value).toBe(null, `Expected trigger to be cleared when option value is not found.`);
+ expect(trigger.textContent)
+ .not.toContain('Pizza', `Expected trigger to be cleared when option value is not found.`);
+
+ trigger.click();
+ fixture.detectChanges();
+
+ const options =
+ overlayContainerElement.querySelectorAll('md-option') as NodeListOf;
+ expect(options[1].classList)
+ .not.toContain('md-selected', `Expected option with the old value not to be selected.`);
+ });
+
+
+ it('should clear the selection when the control is reset', () => {
+ fixture.componentInstance.control.setValue('pizza-1');
+ fixture.detectChanges();
+
+ fixture.componentInstance.control.reset();
+ fixture.detectChanges();
+
+ const value = fixture.debugElement.query(By.css('.md-select-value'));
+ expect(value).toBe(null, `Expected trigger to be cleared when option value is not found.`);
+ expect(trigger.textContent)
+ .not.toContain('Pizza', `Expected trigger to be cleared when option value is not found.`);
+
+ trigger.click();
+ fixture.detectChanges();
+
+ const options =
+ overlayContainerElement.querySelectorAll('md-option') as NodeListOf;
+ expect(options[1].classList)
+ .not.toContain('md-selected', `Expected option with the old value not to be selected.`);
+ });
+
it('should set the control to touched when the select is touched', () => {
expect(fixture.componentInstance.control.touched)
.toEqual(false, `Expected the control to start off as untouched.`);
diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts
index e4b2eb936a4c..98add447d51a 100644
--- a/src/lib/select/select.ts
+++ b/src/lib/select/select.ts
@@ -277,11 +277,7 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
return;
}
- this.options.forEach((option: MdOption) => {
- if (option.value === value) {
- option.select();
- }
- });
+ this._setSelectionByValue(value);
}
/**
@@ -378,6 +374,31 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
scrollContainer.scrollTop = this._scrollTop;
}
+ /**
+ * Sets the selected option based on a value. If no option can be
+ * found with the designated value, the select trigger is cleared.
+ */
+ private _setSelectionByValue(value: any): void {
+ this.options.forEach((option: MdOption) => {
+ if (option.value === value) {
+ option.select();
+ }
+ });
+
+ if (this.selected && this.selected.value !== value) {
+ this._clearSelection();
+ }
+ }
+
+ /** Clears the select trigger and deselects every option in the list. */
+ private _clearSelection(): void {
+ this._selected = null;
+ this._updateOptions();
+
+ // this must happen after change detection so the value doesn't animate
+ Promise.resolve(null).then(() => this._placeholderState = '');
+ }
+
private _getTriggerRect(): ClientRect {
return this.trigger.nativeElement.getBoundingClientRect();
}