九保すこひです(フリーランスのITコンサルタント、エンジニア)
さてさて、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にセットすれば「よく使う文字列ランキング」が入力候補になって便利かなと考えてました。
ぜひ皆さんも試してみてくださいね。
ではでは〜❗
「わかりやすい表現の技術、という本を読んでます。
ユーザビリティの勉強になります👍」





