Skip to content

Commit d6d63cf

Browse files
authored
Merge pull request #7565 from IgniteUI/dkamburov/fix-7483-9.0.x
fix(auto-complete): unsubscribe, before subscribing again #7483
2 parents e20a9ed + ef853a0 commit d6d63cf

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed

projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,31 @@ describe('IgxAutocomplete', () => {
593593
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
594594
expect(fixture.componentInstance.townSelected).toBe('s');
595595
}));
596+
it('Should trigger onItemSelected only once when the event is cancelled (issue #7483)', fakeAsync(() => {
597+
spyOn(autocomplete.onItemSelected, 'emit').and.callThrough();
598+
599+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
600+
UIInteractions.setInputElementValue(input, 's', fixture);
601+
fixture.detectChanges();
602+
tick();
603+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
604+
expect(fixture.componentInstance.townSelected).toBe('s');
605+
tick();
606+
fixture.detectChanges();
607+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(1);
608+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
609+
610+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
611+
UIInteractions.setInputElementValue(input, 's', fixture);
612+
fixture.detectChanges();
613+
tick();
614+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
615+
expect(fixture.componentInstance.townSelected).toBe('s');
616+
tick();
617+
fixture.detectChanges();
618+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(2);
619+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
620+
}));
596621
it('Should call onInput/open/close methods properly', fakeAsync(() => {
597622
let startsWith = 'g';
598623
spyOn(autocomplete, 'onInput').and.callThrough();

projects/igniteui-angular/src/lib/directives/autocomplete/autocomplete.directive.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
NgModule, ElementRef, HostListener, ChangeDetectorRef, OnDestroy } from '@angular/core';
44
import { NgModel, FormControlName } from '@angular/forms';
55
import { CommonModule } from '@angular/common';
6-
import { Subject } from 'rxjs';
6+
import { Subject, Subscription } from 'rxjs';
77
import { first, takeUntil } from 'rxjs/operators';
88
import { CancelableEventArgs, IBaseEventArgs } from '../../core/utils';
99
import { OverlaySettings, AbsoluteScrollStrategy, IScrollStrategy, IPositionStrategy, AutoPositionStrategy } from '../../services/index';
@@ -68,6 +68,9 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
6868
excludePositionTarget: true
6969
};
7070

71+
/** @hidden @internal */
72+
private subscriptions: Subscription[] = [];
73+
7174
protected id: string;
7275
protected dropDownOpened$ = new Subject<boolean>();
7376
protected get model() {
@@ -280,9 +283,18 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
280283
// If no drop-down width is set, the drop-down will be as wide as the autocomplete input;
281284
this.target.width = this.target.width || (this.parentElement.clientWidth + 'px');
282285
this.target.open(this.settings);
283-
this.target.onSelection.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.select);
284-
this.target.onOpened.pipe(first()).subscribe(this.highlightFirstItem);
285-
this.target.children.changes.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.highlightFirstItem);
286+
287+
// unsubscribe from previous subscriptions, before creating new subscriptions.
288+
this.unsubscribe();
289+
290+
this.subscriptions.push(this.target.onSelection.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.select));
291+
this.subscriptions.push(this.target.onOpened.pipe(first()).subscribe(this.highlightFirstItem));
292+
this.subscriptions.push(this.target.children.changes.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.highlightFirstItem));
293+
}
294+
295+
/** @hidden @internal */
296+
private unsubscribe() {
297+
this.subscriptions.forEach(subscription => subscription.unsubscribe());
286298
}
287299

288300
private get collapsed(): boolean {

0 commit comments

Comments
 (0)