Skip to content

Commit e4db4b7

Browse files
authored
Merge pull request #7564 from IgniteUI/dkamburov/fix-7483-9.1.x
fix(auto-complete): unsubscribe, before subscribing again #7483
2 parents 65bfe7f + e14cad8 commit e4db4b7

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
@@ -592,6 +592,31 @@ describe('IgxAutocomplete', () => {
592592
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
593593
expect(fixture.componentInstance.townSelected).toBe('s');
594594
}));
595+
it('Should trigger onItemSelected only once when the event is cancelled (issue #7483)', fakeAsync(() => {
596+
spyOn(autocomplete.onItemSelected, 'emit').and.callThrough();
597+
598+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
599+
UIInteractions.setInputElementValue(input, 's', fixture);
600+
fixture.detectChanges();
601+
tick();
602+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
603+
expect(fixture.componentInstance.townSelected).toBe('s');
604+
tick();
605+
fixture.detectChanges();
606+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(1);
607+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
608+
609+
fixture.componentInstance.onItemSelected = (args) => { args.cancel = true; };
610+
UIInteractions.setInputElementValue(input, 's', fixture);
611+
fixture.detectChanges();
612+
tick();
613+
UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
614+
expect(fixture.componentInstance.townSelected).toBe('s');
615+
tick();
616+
fixture.detectChanges();
617+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledTimes(2);
618+
expect(autocomplete.onItemSelected.emit).toHaveBeenCalledWith({ value: 'Sofia', cancel: true });
619+
}));
595620
it('Should call onInput/open/close methods properly', fakeAsync(() => {
596621
let startsWith = 'g';
597622
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
@@ -15,7 +15,7 @@ import {
1515
} from '@angular/core';
1616
import { NgModel, FormControlName } from '@angular/forms';
1717
import { CommonModule } from '@angular/common';
18-
import { Subject } from 'rxjs';
18+
import { Subject, Subscription } from 'rxjs';
1919
import { first, takeUntil } from 'rxjs/operators';
2020
import { CancelableEventArgs, IBaseEventArgs } from '../../core/utils';
2121
import {
@@ -91,6 +91,9 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
9191
excludePositionTarget: true
9292
};
9393

94+
/** @hidden @internal */
95+
private subscriptions: Subscription[] = [];
96+
9497
protected id: string;
9598
protected dropDownOpened$ = new Subject<boolean>();
9699
protected get model() {
@@ -303,9 +306,18 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
303306
// if no drop-down width is set, the drop-down will be as wide as the autocomplete input;
304307
this.target.width = this.target.width || (this.parentElement.clientWidth + 'px');
305308
this.target.open(this.settings);
306-
this.target.onSelection.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.select);
307-
this.target.onOpened.pipe(first()).subscribe(this.highlightFirstItem);
308-
this.target.children.changes.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.highlightFirstItem);
309+
310+
// unsubscribe from previous subscriptions, before creating new subscriptions.
311+
this.unsubscribe();
312+
313+
this.subscriptions.push(this.target.onSelection.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.select));
314+
this.subscriptions.push(this.target.onOpened.pipe(first()).subscribe(this.highlightFirstItem));
315+
this.subscriptions.push(this.target.children.changes.pipe(takeUntil(this.dropDownOpened$)).subscribe(this.highlightFirstItem));
316+
}
317+
318+
/** @hidden @internal */
319+
private unsubscribe() {
320+
this.subscriptions.forEach(subscription => subscription.unsubscribe());
309321
}
310322

311323
private get collapsed(): boolean {

0 commit comments

Comments
 (0)