Skip to content

Commit ea4d028

Browse files
authored
fix(core): combobox handle IME input correctly to prevent accidental deletion of characters (#12340)
* fix(core): handle IME input correctly to prevent accidental deletion of characters closes [#12232](#12232) ## Description - Added handling for `compositionstart` and `compositionend` events to properly manage IME input (e.g., Chinese, Japanese). - Introduced `isComposing` flag to bypass autocomplete logic during IME composition. - Updated `inputText` synchronization after IME input ends to ensure it matches the finalized value. - Prevented unwanted modifications of input value when using IME, addressing the issue where typing and deleting partially composed characters could remove the last English character. * fix(core): combobox handle IME input correctly to prevent accidental deletion of characters closes [#12232](#12232) ## Description Fixed `isComposing` prefix
1 parent b47940e commit ea4d028

File tree

1 file changed

+20
-3
lines changed

1 file changed

+20
-3
lines changed

libs/cdk/utils/directives/auto-complete/auto-complete.directive.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Directive, ElementRef, EventEmitter, Input, NgZone, Output, inject } fr
33
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
44
import { fromEvent, map, switchMap } from 'rxjs';
55
import { first } from 'rxjs/operators';
6-
import { KeyUtil } from '../../functions/key-util';
6+
import { KeyUtil } from '../../functions';
77

88
export interface AutoCompleteEvent {
99
term: string;
@@ -57,6 +57,9 @@ export class AutoCompleteDirective {
5757
/** @hidden */
5858
private lastKeyUpEvent: KeyboardEvent;
5959

60+
/** @hidden */
61+
private _isComposing = false;
62+
6063
/** @hidden */
6164
private readonly _elementRef = inject(ElementRef);
6265

@@ -72,6 +75,12 @@ export class AutoCompleteDirective {
7275
*/
7376
this._zone.runOutsideAngular(() => {
7477
const keyupEvent = fromEvent<KeyboardEvent>(this._elementRef.nativeElement, 'keyup');
78+
const compositionStartEvent = fromEvent<CompositionEvent>(
79+
this._elementRef.nativeElement,
80+
'compositionstart'
81+
);
82+
const compositionEndEvent = fromEvent<CompositionEvent>(this._elementRef.nativeElement, 'compositionend');
83+
7584
keyupEvent
7685
.pipe(
7786
switchMap((evt) =>
@@ -83,6 +92,15 @@ export class AutoCompleteDirective {
8392
takeUntilDestroyed()
8493
)
8594
.subscribe((evt) => this._handleKeyboardEvent(evt));
95+
96+
compositionStartEvent.pipe(takeUntilDestroyed()).subscribe(() => {
97+
this._isComposing = true;
98+
});
99+
100+
compositionEndEvent.pipe(takeUntilDestroyed()).subscribe(() => {
101+
this._isComposing = false;
102+
this.inputText = this._elementRef.nativeElement.value;
103+
});
86104
});
87105
}
88106

@@ -92,7 +110,7 @@ export class AutoCompleteDirective {
92110

93111
/** @hidden */
94112
_handleKeyboardEvent(event: KeyboardEvent): void {
95-
if (this.enable) {
113+
if (this.enable && !this._isComposing) {
96114
if (KeyUtil.isKeyCode(event, this._stopKeys)) {
97115
this._elementRef.nativeElement.value = this.inputText;
98116
} else if (KeyUtil.isKeyCode(event, this._completeKeys)) {
@@ -101,7 +119,6 @@ export class AutoCompleteDirective {
101119
} else if (KeyUtil.isKeyCode(event, this._fillKeys)) {
102120
this._sendCompleteEvent(false);
103121
} else if (!this._isControlKey(event) && this.inputText) {
104-
/** Prevention from triggering typeahead, when having crtl/cmd + keys */
105122
if (!this._triggerTypeAhead()) {
106123
return;
107124
}

0 commit comments

Comments
 (0)