九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、Vue 3
が登場してから少し時間が経ちました。基本的には前回バージョンと同じ構成になっているので、移行はそれほど手間取ることはないと思います。
※ ただし、Laravel + npm
でVue 3
を使おうとするとシングル・ファイル・コンポーネントがうまく処理できないので個人的にはガンガン使ってません💧これは、Laravel Mix 6
で対応するとのことです。
そして、そんなVue
で今回作ってみるのが、
入力候補から選択できる機能
です。
例えば、次のようなカンジですね。
というのも、「めんどうな入力をできるだけ省略したい」というのは誰でも要望が高いでしょうし、特に毎日の業務で使う場合は「またおんなじ入力かよ・・・」とうんざりするはずだからです。
そして、そんなときに思い出したのがHTML 5
の<datalist></datalist>
です。(これ、すっかり忘れてました😂)
入力候補と言えば、その昔は select2 などJSパッケージで実装していましたが、なんと今はHTML
だけでOKなんですね。
そこで❗
今回はVue(バージョン3
&2
)で簡単にdatalist
が使えるディレクティブをつくってみます。
ぜひユーザビリティのために試してみてください😊✨
(最後に実際開発したソースコード一式をダウンロードできますよ👍)
「ルパン三世 Part1見てます。
やっぱり面白いですね」
開発環境: Vue 3.0.3、Vue 2.6.12
やりたいこと
ある<Input>
タグに配列データをセットするだけでdatalist
が機能するようにします。
そのため、今回はVue
で独自のプロパティが使えるようになる「ディレクティブ」を使って実装します。
サンプルはこんなカンジです。
<input type="text" v-data-list="values">
なお、今回はコード量がそれほど多くないのでVue 3
だけでなく、Vue 2
での実装も合わせてご紹介します。
この機会に、バージョン2と3の違いを比べてみてくださいね👍
datalistの使い方
まず、<input>
に入力候補を表示できるようになる<datalist>
タグの使い方です。(ご存知の方は次まで飛ばしてください)
<!-- 入力部分 --> <input type="text" list="fruits"> <!-- リスト部分 --> <datalist id="fruits"> <option value="リンゴ"> <option value="ミカン"> <option value="バナナ"> </datalist>
ここで重要なのが、fruits
の部分です。
<input>
ではlist="****"
の中に、そして<datalist>
ではid="****"
にそれぞれセットし、ペアをつくります。
そして、<input>
にフォーカスが当たると(入力状態になると)、<datalist>
の部分が表示され、各項目が選択できるようになります。
しかも、<datalist>
はとても有能で、例えば上の場合「ゴ」と入力するとその文字が含まれている「リンゴ」だけに絞り込んでくれます。
ちなみに、datalist
にlabel="***"
をつけるとちょっとした説明書きを追加することができます。
<datalist id="reservation_dates"> <option label="今日">20020-01-01</option> <option label="明日">20020-01-02</option> <option label="明後日">20020-01-03</option> </datalist>
実際の表示はこうなります。
今回はせっかくなので、このlabel
も独自ディレクティブで使えるようにしてみます。
では、実際にやってみましょう❗
Vue 3でdatalist入力候補を有効にする
以下がサンプルコードになります。(デモページはこちら)
<html> <body> <div id="app"> <!-- ③ ディレクティブを使う --> 【文字列】<br> <input type="text" v-data-list="colors"> <br><br> 【数値】<br> <input type="text" v-data-list="numbers"> <br><br> 【日付】<br> <input type="date" v-data-list="dates"> </div> <script src="https://unpkg.com/vue@3.0.3/dist/vue.global.prod.js"></script> <script> // ① ディレクティブを定義する const dataListDirective = { mounted(el, binding) { const listValues = binding.value; const randomKey = 'datalist-'+ Math.random().toString(36).substring(7); let dataList = document.createElement('datalist'); dataList.setAttribute('id', randomKey); el.setAttribute('list', randomKey) for(let listValue of listValues) { let option = document.createElement('option'); if(typeof listValue === 'object') { // ラベル付きの場合 option.label = listValue.label; option.value = listValue.value; } else { option.value = listValue; } dataList.appendChild(option); } document.querySelector('body').appendChild(dataList); } }; Vue.createApp({ data() { return { colors: ['赤', '青', '黄色', '黒','白'], numbers: [500, 1000, 1500], dates: [ { value: '20020-01-01', label: '今日' }, { value: '20020-01-02', label: '明日' }, { value: '20020-01-03', label: '明後日' }, ] } } }) .directive('data-list', dataListDirective) // ② ディレクティブを有効にする .mount('#app'); </script> </body> </html>
では、中身をひとつずつご紹介します。
① ディレクティブを定義する
まずJavaScript
部分に「ディレクティブ」の本体をつくります。
この中でやっている手順は次のとおりです。
- ディレクティブにセットされた入力候補(配列データ)を取得
- ランダムな文字列をつくって、それぞれ <input> と <datalist> にセット
- datalist に入力候補となる文字列をセット ※
- <body> タグに <datalist> を挿入
- 完了!
※ なお、セットされたデータが以下のようなコレクション(オブジェクトの配列)の場合は自動的にlabel
もセットできるようにしています。
[ { value: '20020-01-01', label: '今日' }, { value: '20020-01-02', label: '明日' }, { value: '20020-01-03', label: '明後日' }, ]
なお、ランダムな文字列をつくっているのは、v-data-list
が複数呼び出されてもid
が重複しないようにするためです。
② ディレクティブを有効にする
先ほどつくったdataListDirective
は、単体では単なるオブジェクトなので、これを有効にする必要があります。
.directive('data-list', dataListDirective)
※なお、v-
の部分は自動で付与されるので第一引数は、data-list
のみでOKです。
③ ディレクティブを使う
そして最後にv-data-list
の使い方です。
ここは、表示したい入力候補(配列)をv-data-list="****"
の中に入れてあげるだけでOKです。
<input type="text" v-data-list="colors">
配列は、以下のようにVue
本体で定義してください。
Vue.createApp({ data() { return { colors: ['赤', '青', '黄色', '黒','白'], numbers: [500, 1000, 1500], dates: [ { value: '20020-01-01', label: '今日' }, { value: '20020-01-02', label: '明日' }, { value: '20020-01-03', label: '明後日' }, ] } } })
⚠ Vue 2
とは違い、data
は関数で指定するよう変更になっています。
なお、文字列だや数値だけでなく、日付選択の<input type="date">
でも使えます。ナイスですね👍
Vue 2でdatalist入力候補を有効にする
では、Vue 2
の方でもつくってみましょう。(デモページはこちら)
とは言っても、ほぼセットの仕方が違うだけです。
<html> <body> <div id="app"> <!-- ③ ディレクティブを使う --> 【文字列】<br> <input type="text" v-data-list="colors"> <br><br> 【数値】<br> <input type="text" v-data-list="numbers"> <br><br> 【日付】<br> <input type="date" v-data-list="dates"> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js"></script> <script> // ① ディレクティブを定義する const dataListDirective = { inserted(el, binding) { // 省略: Vue 3バージョンと同じです } }; new Vue({ el: '#app', directives: { 'data-list': dataListDirective }, // ② ディレクティブを有効にする data: { colors: ['赤', '青', '黄色', '黒','白'], numbers: [500, 1000, 1500], dates: [ { value: '20020-01-01', label: '今日' }, { value: '20020-01-02', label: '明日' }, { value: '20020-01-03', label: '明後日' }, ] } }); </script> </body> </html>
なお、ディレクティブ内のinserted
はVue 3
でいうところのmounted
に相当します。
【ディレクティブ内のパラメータの変化】
Vue 2 | Vue 3 |
---|---|
bind | beforeMount |
inserted | mounted |
componentUpdated | updated |
unbind | unmounted |
なし | beforeUpdate |
なし | beforeUnmount |
update | なし |
ダウンロードする
今回実際に開発したソースコード一式を以下からダウンロードすることができます。
Vue + datalist で簡単に入力候補を有効にする※ CDN
を使っているのでダウンロードして展開するだけで実行できますよ😊
おわりに
ということで、今回はVue + datalist
でユーザビリティを向上させてみました。
IE
や(古い)edge
がほぼ消滅してくれたので、こういったHTML 5
やCSS 3
などは積極的に使っていきたいですね。(もう一度ザーッとチェックしとこうかな❓)
なお、datalist
は当初すっかり忘れていましたが、便利ですし、使い方も簡単なので今後実際の開発でも使っていこうと思います。
ちなみに、datalist
のアイデアとしては「直近に保存された文字列」をGROUP BY
で集計し、個数が多いものからdatalist
にセットすれば「よく使う文字列ランキング」が入力候補になって便利かなと考えてました。
ぜひ皆さんも試してみてくださいね。
ではでは〜❗
「わかりやすい表現の技術、という本を読んでます。
ユーザビリティの勉強になります👍」