【Vue.js】Element Uiでautocompleteのサジェスト機能を導入する方法と使い方!
この記事からわかること
- Vue.jsのElement Uiの機能
- autocompleteの導入方法と使い方
- v-modelとリンクづける方法
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
豊富なコンポーネントと導入のしやすさから人気のVue.jsのUIライブラリの1つ「Element Ui」。
その中の「autocomplete」を使おうとした際に試行錯誤した部分と導入方法、使い方も併せてまとめておきます。
Element Uiでautocompleteを導入しよう!
Element Ui自体の導入方法はここでは割愛します。詳しくはこちらの記事をご覧ください。
ライブラリの導入ができたら「autocomplete」を使用できるように設定をしていきます。プロジェクトの中の「src」>「plugins」>「element.js」に追記していきます。
オンデマンドインストールの「element.js」
import Vue from 'vue'
import {
Alert,
Input,
Dialog,
Autocomplete, // 追加
} from 'element-ui'
import lang from 'element-ui/lib/locale/lang/ja'
import 'element-ui/lib/theme-chalk/index.css';
import locale from 'element-ui/lib/locale'
locale.use(lang)
const components = [
Alert,
Input,
Dialog,
Autocomplete, // 追加
];
const Element = {
install(Vue) {
components.forEach(component => {
Vue.component(component.name, component)
})
}
}
Vue.use(Element, { locale })
オンデマンドインストールでのElement Uiでは「element.js」に使いたいコンポーネントを追加していくだけでOKです。これで<el-autocomplete>
タグが使用可能になりました。
el-autocompleteの使い方と特徴
el-autocompleteはinput要素にサジェスト(入力アシスト)機能を追加できるコンポーネントです。
使用方法は簡単で公式ページのデモコードをそのままコピペして貼り付けるだけで動作してくれます。そのままコピペすると2つのタイプのautocompleteが動きます。
- Input要素をアクティブ時に全てのサジェストが出るタイプ
- 入力された文字を識別して該当のサジェストが出るタイプ
公式ページのデモコード
<el-row class="demo-autocomplete"> <!-- タイプ1 --> <el-col :span="12"> <div class="sub-title">list suggestions when activated</div> <el-autocomplete class="inline-input" v-model="state1" :fetch-suggestions="querySearch" placeholder="Please Input" @select="handleSelect" ></el-autocomplete> </el-col> <!-- タイプ2 --> <el-col :span="12"> <div class="sub-title">list suggestions on input</div> <el-autocomplete class="inline-input" v-model="state2" :fetch-suggestions="querySearch" placeholder="Please Input" :trigger-on-focus="false" @select="handleSelect" ></el-autocomplete> </el-col> </el-row> <script>
export default { data() { return { links: [], state1: '', state2: '' }; }, methods: { querySearch(queryString, cb) { var links = this.links; var results = queryString ? links.filter(this.createFilter(queryString)) : links; // call callback function to return suggestions cb(results); }, createFilter(queryString) { return (link) => { return (link.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0); }; }, loadAll() { return [ { "value": "vue", "link": "https://github.com/vuejs/vue" }, { "value": "element", "link": "https://github.com/ElemeFE/element" }, { "value": "cooking", "link": "https://github.com/ElemeFE/cooking" }, { "value": "mint-ui", "link": "https://github.com/ElemeFE/mint-ui" }, { "value": "vuex", "link": "https://github.com/vuejs/vuex" }, { "value": "vue-router", "link": "https://github.com/vuejs/vue-router" }, { "value": "babel", "link": "https://github.com/babel/babel" } ]; }, handleSelect(item) { console.log(item); } }, mounted() { this.links = this.loadAll(); } } </script>
デフォルトで用意されているメソッドとその役割と意味は以下の通りだと思います。
メソッドの意味
- querySearch:入力文字のフィルター検索実行
- createFilter:マッチ検索フィルター本体
- loadAll:フィルターデータ
- handleSelect:選択されたサジェストを表示
サジェストデータをAPIで取得させる
実際にデモコードを使ってカスタマイズしてみます。今回はAPIで連想配列を取得しサジェストのデータに組み込んでいきます。
Laravelのweb.phpとコントローラーを編集しURL/api/category
で以下のような連想配列を返すように設定しておきます。
{"category_id":1,"value":"食事"},
{"category_id":2,"value":"スポーツ"},
{"category_id":3,"value":"読書"},
{"category_id":4,"value":"住まい"},
{"category_id":5,"value":"子供"},
{"category_id":6,"value":"お金"},
{"category_id":7,"value":"生活"}....
web.php
Route::post('/api/category', 'App\Http\Controllers\ApiController@category');
ApiController
public function category()
{
$category = DB::select('SELECT * FROM category');
return $category;
}
今回はデータベースに格納しているカテゴリテーブルの全値を取得させています。
続いてVuexを使って管理している「src」>「store」>「index.js」に以下のように記述します。
export default new Vuex.Store({
strict: true,
state: {
links: [],
},
mutations: {
getCategory(state, api) {
state.links = api;
},
}.
actions: {
async callCategory(context) {
const response = await axios.post("/api/category");
context.commit('getCategory', response.data);
}
}
これで$store.state.links
でAPIで取得している連想配列に参照することができます。
今回はサジェストで選択された連想配列値のcategory_idをdataのcategory_id
に格納するのを目標にしていきます。
<template> <el-autocomplete v-model="category" :fetch-suggestions="querySearch" placeholder="カテゴリ" :class="{err:err.category}" @select="checkPost" @blur="checkPost" ></el-autocomplete> <!-- サジェストから選択された時 @select--> <!-- フォーカスが外れた時 @blur--> </template> <script>
export default { data() { return { category: "", category_id: "", err:{ category:false, }, }; }, computed: { links() { return this.$store.state.links; }, }, methods: { querySearch(queryString, cb) { var links = this.links; var results = queryString ? links.filter(this.createFilter(queryString)) : links; // call callback function to return suggestions cb(results); }, createFilter(queryString) { return (link) => { return ( link.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ); }; }, checkPost(item){ if(item.value !== undefined){ this.category = item.value } if(this.category !== ""){ const target = this.links.find((data)=> {return (data.value === this.category)}); if(target === undefined){ this.err.category= true; }else{ // 選択された正しいカテゴリidを格納 this.category_id =target.category_id; this.err.category= false; }; } }, }, }; </script>
v-on(@)
でサジェストから選択された時とフォーカスが外れた時のイベントを補足し、checkPost
を呼び出します。
checkPost
の引数に変数を渡せば、選択されたサジェストのidとvalueを受け取ることができます。
v-model
を使ってinput要素のvalue属性とdata変数の中身をリンクさせようとしましたがサジェストで選択された値はv-modelの中には自動で格納されないようでした。
なので47行目の部分でdata変数の中に入れ込んでおく必要がありました。
if(item.value !== undefined){
this.category = item.value
}
実際にElement Uiを使って作ったのが以下のwebアプリです。サジェスト機能も使っているので除いてみてください!
子育て知識共有サイト-mikata-まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。