Skip to content

Commit 6108563

Browse files
jefersonestevotinayuangao
authored andcommitted
bug(autocomplete): deselect the other options when the user select an option (#3690)
* bug(autocomplete): deselect the other options when the user select one from the autocomplete Fixes #3689 * bug(autocomplete): only call deselect on the previous selected option. Unit tests.
1 parent 1ae81a4 commit 6108563

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/lib/autocomplete/autocomplete-trigger.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,25 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
307307
*/
308308
private _setValueAndClose(event: MdOptionSelectionChange | null): void {
309309
if (event) {
310+
this._clearPreviousSelectedOption(event.source);
310311
this._setTriggerValue(event.source.value);
311312
this._onChange(event.source.value);
312313
}
313314

314315
this.closePanel();
315316
}
316317

318+
/**
319+
* Clear any previous selected option and emit a selection change event for this option
320+
*/
321+
private _clearPreviousSelectedOption(skip: MdOption) {
322+
this.autocomplete.options.forEach((option) => {
323+
if (option != skip && option.selected) {
324+
option.deselect();
325+
}
326+
});
327+
}
328+
317329
private _createOverlay(): void {
318330
this._portal = new TemplatePortal(this.autocomplete.template, this._viewContainerRef);
319331
this._overlayRef = this._overlay.create(this._getOverlayConfig());

src/lib/autocomplete/autocomplete.spec.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,69 @@ describe('MdAutocomplete', () => {
918918

919919
});
920920

921+
describe('Option selection', () => {
922+
let fixture: ComponentFixture<SimpleAutocomplete>;
923+
924+
beforeEach(() => {
925+
fixture = TestBed.createComponent(SimpleAutocomplete);
926+
fixture.detectChanges();
927+
928+
fixture.componentInstance.trigger.openPanel();
929+
fixture.detectChanges();
930+
});
931+
932+
it('should deselect any other selected option', async(() => {
933+
let options =
934+
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
935+
options[0].click();
936+
fixture.detectChanges();
937+
938+
fixture.whenStable().then(() => {
939+
fixture.detectChanges();
940+
941+
let componentOptions = fixture.componentInstance.options.toArray();
942+
expect(componentOptions[0].selected)
943+
.toBe(true, `Clicked option should be selected.`);
944+
945+
options =
946+
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
947+
options[1].click();
948+
fixture.detectChanges();
949+
950+
expect(componentOptions[0].selected)
951+
.toBe(false, `Previous option should not be selected.`);
952+
expect(componentOptions[1].selected)
953+
.toBe(true, `New Clicked option should be selected.`);
954+
955+
});
956+
}));
957+
958+
it('should call deselect only on the previous selected option', async(() => {
959+
let options =
960+
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
961+
options[0].click();
962+
fixture.detectChanges();
963+
964+
fixture.whenStable().then(() => {
965+
fixture.detectChanges();
966+
967+
let componentOptions = fixture.componentInstance.options.toArray();
968+
componentOptions.forEach(option => spyOn(option, 'deselect'));
969+
970+
expect(componentOptions[0].selected)
971+
.toBe(true, `Clicked option should be selected.`);
972+
973+
options =
974+
overlayContainerElement.querySelectorAll('md-option') as NodeListOf<HTMLElement>;
975+
options[1].click();
976+
fixture.detectChanges();
977+
978+
expect(componentOptions[0].deselect).toHaveBeenCalled();
979+
componentOptions.slice(1).forEach(option => expect(option.deselect).not.toHaveBeenCalled());
980+
});
981+
}));
982+
});
983+
921984
describe('misc', () => {
922985

923986
it('should allow basic use without any forms directives', () => {

0 commit comments

Comments
 (0)