Skip to content

Commit

Permalink
fix(core): handle IME input correctly to prevent accidental deletion …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
khotcholavaSuzy committed Aug 30, 2024
1 parent b017835 commit b8728bc
Showing 1 changed file with 20 additions and 3 deletions.
23 changes: 20 additions & 3 deletions libs/cdk/utils/directives/auto-complete/auto-complete.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Directive, ElementRef, EventEmitter, Input, NgZone, Output, inject } fr
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { fromEvent, map, switchMap } from 'rxjs';
import { first } from 'rxjs/operators';
import { KeyUtil } from '../../functions/key-util';
import { KeyUtil } from '../../functions';

export interface AutoCompleteEvent {
term: string;
Expand Down Expand Up @@ -57,6 +57,9 @@ export class AutoCompleteDirective {
/** @hidden */
private lastKeyUpEvent: KeyboardEvent;

/** @hidden */
private isComposing = false;

/** @hidden */
private readonly _elementRef = inject(ElementRef);

Expand All @@ -72,6 +75,12 @@ export class AutoCompleteDirective {
*/
this._zone.runOutsideAngular(() => {
const keyupEvent = fromEvent<KeyboardEvent>(this._elementRef.nativeElement, 'keyup');
const compositionStartEvent = fromEvent<CompositionEvent>(
this._elementRef.nativeElement,
'compositionstart'
);
const compositionEndEvent = fromEvent<CompositionEvent>(this._elementRef.nativeElement, 'compositionend');

keyupEvent
.pipe(
switchMap((evt) =>
Expand All @@ -83,6 +92,15 @@ export class AutoCompleteDirective {
takeUntilDestroyed()
)
.subscribe((evt) => this._handleKeyboardEvent(evt));

compositionStartEvent.pipe(takeUntilDestroyed()).subscribe(() => {
this.isComposing = true;
});

compositionEndEvent.pipe(takeUntilDestroyed()).subscribe(() => {
this.isComposing = false;
this.inputText = this._elementRef.nativeElement.value;
});
});
}

Expand All @@ -92,7 +110,7 @@ export class AutoCompleteDirective {

/** @hidden */
_handleKeyboardEvent(event: KeyboardEvent): void {
if (this.enable) {
if (this.enable && !this.isComposing) {
if (KeyUtil.isKeyCode(event, this._stopKeys)) {
this._elementRef.nativeElement.value = this.inputText;
} else if (KeyUtil.isKeyCode(event, this._completeKeys)) {
Expand All @@ -101,7 +119,6 @@ export class AutoCompleteDirective {
} else if (KeyUtil.isKeyCode(event, this._fillKeys)) {
this._sendCompleteEvent(false);
} else if (!this._isControlKey(event) && this.inputText) {
/** Prevention from triggering typeahead, when having crtl/cmd + keys */
if (!this._triggerTypeAhead()) {
return;
}
Expand Down

0 comments on commit b8728bc

Please sign in to comment.