vue-touch-keyboardをv-model(databind)と共存させる

Vue.js v2でソフトウェアキーボードを使おうとすると、vue-touch-keyboardが第一候補に挙がるわけですが、公式のREADMEやJSFiddleのサンプルだけではイマイチピンとこないところがあるわけです。
その典型例が「どうやってv-modelでのdatabindと共存するの?」なわけですが、今回はそれをテーマにしたいと思います。

まず、オリジナルのJSFiddleサンプルをforkして、3つあるinputに同じ変数(ここではvm.data.value)をv-modelでdatabindさせたものがこれです。

試してみるとすぐわかりますが、ソフトウェアキーボードから入力した値がclose(またはnext)キーの押下で消えてしまいます。
これはvue-touch-keyboardが入力対象のDOMに対してのみ値を設定しており、databindされたviewmodel側の値の更新を一切行ってないからです。

では、どうすればviewmodel側の値を更新できるようになるのか?
これは「Vue.jsがDOMのnative eventをフックして値の変更を検知している」ことから、vue-touch-keyboardが入力対象としているDOMに対して'input'のnative eventを発火させればよいことになります。
なお「native event」とjQueryのtriggerで発火させることができる「jQuery event」とは別物なので注意してください(単なる「event」ではどちらのことを指しているか不明なので、native event/jQuery eventと呼び分けます)。
close及びnextキー押下の「確定」のタイミングで値の変更通知を発生させるようにしたものがこれです。

キモはこのコードになります。

        accept(text) {
          console.log("Input text: " + text);
          this.change(text); ←ここでnative event発火メソッドを呼ぶ

          this.hide();
        },
        change(text) {native event発火処理の実装
          // Trigger native 'input' event to notify Vue that the value has changed
          var evt = document.createEvent('HTMLEvents');
          evt.initEvent('input', true, true);
          this.input.dispatchEvent(evt);
        },

vue-touch-keyboardタグでの定義:accept="accept"により、close及びnextキーを押下するとvm.acceptメソッドが呼ばれます。

<vue-touch-keyboard id="keyboard" v-if="visible" :layout="layout" :cancel="hide" :accept="accept" :input="input" :next="next" />

なので、vm.accept内でnative eventを発火させればよいわけです。実際にeventを発火させるコードはvm.changeメソッドに記載しています。

現在ソフトウェアキーボードが入力対象としているDOMはvm.showメソッドの下記の処理によりthis.inputに格納されていますので、

        show(e) {
          this.input = e.target;

this.inputに対してdispatchEventを実行することでnative eventを発行できます(発行するeventの内容はevtに定義)。

さらに一歩すすんで、キー入力内容をリアルタイムで通知するバージョンはこれになります。

3つのinputに対して同じ値をdatabindしてあるので、リアルタイムに値が変更されていることが良くわかると思います。

これはvue-touch-keyboardタグに対して追加で:changeイベントハンドラの定義を行うだけです。
先ほどの実装で既にnative eventの発行をvm.changeメソッドに分離、かつchangeイベントハンドラのI/F要件を満たしてあるようにあったので、たったこれだけの追加で済みます。

<vue-touch-keyboard id="keyboard" v-if="visible" :layout="layout" :cancel="hide" :accept="accept" :input="input" :next="next" :change="change"←これ />

これでvue-touch-keyboardとv-modelを共存でき、かつリアルタイムに値の同期が行えるようになりました。めでたし、めでたし。

次回は引き続きvue-touch-keyboardでオリジナルのkeylayoutを作ってみたいと思います。