やりたいことと方法を手短に
Google の検索欄って、変換を確定する前から検索してくれて便利ですよね。
Angular でこのように変換確定前の入力値を使いたいときには COMPOSITION_BUFFER_MODE
が役に立ちます。モジュールやコンポーネントの providers
で COMPOSITION_BUFFER_MODE
を false
にすれば、 IME の変換が確定していなくても input の入力値がモデルに反映されます。
詳しい説明
入力された文字を表示するだけの簡単なコードを考えます。
<input ngModel #text="ngModel"> {{ text.value }}
これを PC のブラウザで操作すると、変換を確定するまで入力した文字が表示されないはずです。なぜこのような動作になるかというと、 Angular が変換が確定するまでモデルに入力値を反映させていないからです。具体的な処理は DefaultValueAccessor に書いてあります。
この挙動は COMPOSITION_BUFFER_MODE
の値を設定することで変えることができます。
-
true
なら変換を確定するまでモデルに反映されません。 -
false
なら変換を確定する前でもモデルに反映されます。 - 無指定の時は Android なら
true
、それ以外ならfalse
を指定したときと同じ動作をします。詳しくは DefaultValueAccessor の実装を参照
最初に書いたデモでは、これら3種類の設定について動作を確認することができます。忙しい人のために、実際に操作している様子の動画を貼っておきます。 false
のときだけ変換確定前でも値を表示できていますね。
変換を確定する前でもモデルに反映させるために false
にするコードのイメージです。このように AppModule
に書いてもいいですし、コンポーネント単位で挙動を変えたいときはコンポーネント側に書いても構いません。
import { COMPOSITION_BUFFER_MODE } from '@angular/forms'
@NgModule({
// ...
providers: [
// 変換が確定する前でも input の値を得られるようにするため
{ provide: COMPOSITION_BUFFER_MODE, useValue: false }
]
})
export class AppModule {}
これでサジェストや文字数カウントなどの機能も思いのまま! Happy Angular Life!
参考
- JavaScript とクロスブラウザでの IME event handling (2017年) - たにしきんぐダム - input イベントや compositionend イベント周りの話が参考になりました
- fix(forms): make composition event buffering configurable (#15256) · angular/angular@5efc860 - この処理が入ったコミット