mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(select): clear select if no option matches value (#2110)
Closes #2109
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<p> Status: {{ foodControl.status }} </p>
|
||||
<button md-button (click)="foodControl.setValue('pizza-1')">SET VALUE</button>
|
||||
<button md-button (click)="toggleDisabled()">TOGGLE DISABLED</button>
|
||||
<button md-button (click)="foodControl.reset()">RESET</button>
|
||||
</md-card>
|
||||
</div>
|
||||
|
||||
@@ -30,6 +31,7 @@
|
||||
<button md-button (click)="currentDrink='sprite-1'">SET VALUE</button>
|
||||
<button md-button (click)="isRequired=!isRequired">TOGGLE REQUIRED</button>
|
||||
<button md-button (click)="isDisabled=!isDisabled">TOGGLE DISABLED</button>
|
||||
<button md-button (click)="drinkControl.reset()">RESET</button>
|
||||
</md-card>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -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<HTMLElement>;
|
||||
options[1].click();
|
||||
fixture.detectChanges();
|
||||
|
||||
trigger.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
// must wait for initial writeValue promise to finish
|
||||
fixture.whenStable().then(() => {
|
||||
expect(fixture.componentInstance.select._keyManager.focusedItemIndex).toEqual(1);
|
||||
fixture.componentInstance.control.setValue('pizza-1');
|
||||
fixture.detectChanges();
|
||||
|
||||
trigger.click();
|
||||
fixture.detectChanges();
|
||||
|
||||
// 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<HTMLElement>;
|
||||
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<HTMLElement>;
|
||||
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.`);
|
||||
|
||||
@@ -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,30 @@ 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 {
|
||||
const options = this.options.toArray();
|
||||
|
||||
for (let i = 0; i < this.options.length; i++) {
|
||||
if (options[i].value === value) {
|
||||
options[i].select();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear selection if no item was selected.
|
||||
this._clearSelection();
|
||||
}
|
||||
|
||||
/** Clears the select trigger and deselects every option in the list. */
|
||||
private _clearSelection(): void {
|
||||
this._selected = null;
|
||||
this._updateOptions();
|
||||
}
|
||||
|
||||
private _getTriggerRect(): ClientRect {
|
||||
return this.trigger.nativeElement.getBoundingClientRect();
|
||||
}
|
||||
@@ -426,6 +446,7 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
|
||||
this._selected = option;
|
||||
this._updateOptions();
|
||||
this._setValueWidth();
|
||||
this._placeholderState = '';
|
||||
if (this.panelOpen) {
|
||||
this.close();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user