Skip to content

Commit 9a4a4cf

Browse files
authored
fix(material/autocomplete): don't emit optionActivated event when option is reset (#23437)
Fixes that we were emitting the `optionActivated` event when the option is reset programmatically when the panel closes. The intent was to only emit the event as a result of a user action. Fixes #23430.
1 parent 4414b04 commit 9a4a4cf

File tree

4 files changed

+48
-2
lines changed

4 files changed

+48
-2
lines changed

src/material-experimental/mdc-autocomplete/autocomplete.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,6 +2789,28 @@ expect(scrollContainer.scrollTop)
27892789
expect(spy.calls.mostRecent().args[0]).toEqual({source: autocomplete, option: options[2]});
27902790
}));
27912791

2792+
it('should not emit the optionActivated event when the active option is reset', fakeAsync(() => {
2793+
const fixture = createComponent(AutocompleteWithActivatedEvent);
2794+
2795+
fixture.detectChanges();
2796+
fixture.componentInstance.trigger.openPanel();
2797+
zone.simulateZoneExit();
2798+
fixture.detectChanges();
2799+
2800+
const input = fixture.nativeElement.querySelector('input');
2801+
const spy = fixture.componentInstance.optionActivated;
2802+
2803+
expect(spy).not.toHaveBeenCalled();
2804+
2805+
dispatchKeyboardEvent(input, 'keydown', DOWN_ARROW);
2806+
fixture.detectChanges();
2807+
expect(spy).toHaveBeenCalledTimes(1);
2808+
2809+
dispatchKeyboardEvent(input, 'keydown', ESCAPE);
2810+
fixture.detectChanges();
2811+
expect(spy).toHaveBeenCalledTimes(1);
2812+
}));
2813+
27922814
it('should be able to set a custom panel connection element', () => {
27932815
const fixture = createComponent(AutocompleteWithDifferentOrigin);
27942816

src/material/autocomplete/autocomplete-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,8 +574,8 @@ export abstract class _MatAutocompleteTriggerBase implements ControlValueAccesso
574574
// See: https://www.w3.org/TR/wai-aria-practices-1.1/#textbox-keyboard-interaction
575575
if ((event.keyCode === ESCAPE && !hasModifierKey(event)) ||
576576
(event.keyCode === UP_ARROW && hasModifierKey(event, 'altKey'))) {
577-
this._resetActiveItem();
578577
this._closeKeyEventStream.next();
578+
this._resetActiveItem();
579579

580580
// We need to stop propagation, otherwise the event will eventually
581581
// reach the input itself and cause the overlay to be reopened.

src/material/autocomplete/autocomplete.spec.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,6 +2790,28 @@ expect(container.scrollTop)
27902790
expect(spy.calls.mostRecent().args[0]).toEqual({source: autocomplete, option: options[2]});
27912791
}));
27922792

2793+
it('should not emit the optionActivated event when the active option is reset', fakeAsync(() => {
2794+
const fixture = createComponent(AutocompleteWithActivatedEvent);
2795+
2796+
fixture.detectChanges();
2797+
fixture.componentInstance.trigger.openPanel();
2798+
zone.simulateZoneExit();
2799+
fixture.detectChanges();
2800+
2801+
const input = fixture.nativeElement.querySelector('input');
2802+
const spy = fixture.componentInstance.optionActivated;
2803+
2804+
expect(spy).not.toHaveBeenCalled();
2805+
2806+
dispatchKeyboardEvent(input, 'keydown', DOWN_ARROW);
2807+
fixture.detectChanges();
2808+
expect(spy).toHaveBeenCalledTimes(1);
2809+
2810+
dispatchKeyboardEvent(input, 'keydown', ESCAPE);
2811+
fixture.detectChanges();
2812+
expect(spy).toHaveBeenCalledTimes(1);
2813+
}));
2814+
27932815
it('should be able to set a custom panel connection element', () => {
27942816
const fixture = createComponent(AutocompleteWithDifferentOrigin);
27952817

src/material/autocomplete/autocomplete.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ export abstract class _MatAutocompleteBase extends _MatAutocompleteMixinBase imp
215215
ngAfterContentInit() {
216216
this._keyManager = new ActiveDescendantKeyManager<_MatOptionBase>(this.options).withWrap();
217217
this._activeOptionChanges = this._keyManager.change.subscribe(index => {
218-
this.optionActivated.emit({source: this, option: this.options.toArray()[index] || null});
218+
if (this.isOpen) {
219+
this.optionActivated.emit({source: this, option: this.options.toArray()[index] || null});
220+
}
219221
});
220222

221223
// Set the initial visibility state.

0 commit comments

Comments
 (0)