目次
環境
vue.js : 2.5.8
Vue.Draggable: 2.15.0
はじめに
Vue.Draggableを使いながらリストをフィルタする機能が欲しいと思いました。
しかし、Vue.Draggableの特性と言いますか、制限のようなものでcomputed
が使用できません。
そこで別のやり方で実装しました。
デモ
See the Pen Vue.Draggable filter by カバの樹 (@kabanoki) on CodePen.0
ソース
■CDN
</pre> <pre><!-- CDNJS :: Vue (https://cdnjs.com/) --> <script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script> <!-- CDNJS :: Sortable (https://cdnjs.com/) --> <script src="//cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script> <!-- CDNJS :: Vue.Draggable (https://cdnjs.com/) --> <script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.15.0/vuedraggable.min.js"></script> <!-- Latest compiled and minified CSS --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- Optional theme --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"></pre> <pre>
■HTML
<div id="main"> <div id="selectbox" class="p20"> <label>カテゴリー選択:</label> <select id="shop_category" name="pref" v-model="selectCategory" class="form-control input-lg"> <option value="">-</option> <option v-for="(item, index) in category" v-bind:value="item.no">{{item.name}}</option> </select> </div> <ul class="list-group drag p20"> <draggable :list="filterItems" class="dragArea"> <li class="list-group-item" v-for="item, index in filterItems" :key="item.no"> <label>{{item.name}}</label> </li> </draggable> </ul> </div>
■CSS
.p20{ padding:20px } .normal { background-color: grey; } .dragArea{ min-height: 10px; } .sortable-chosen { opacity: 0.7; background-color:#dcdcdc; } .sortable-ghost { background-color:#dcdcdc; }
■Javascript
var items = [ {no:1, name:'キャベツ', categoryNo:'1'}, {no:2, name:'ステーキ', categoryNo:'2'}, {no:3, name:'リンゴ', categoryNo:'3'}, {no:4, name:'冷蔵庫', categoryNo:'4'}, {no:5, name:'きゅうり', categoryNo:'1'}, {no:6, name:'ハンバーグ', categoryNo:'2'}, {no:7, name:'バナナ', categoryNo:'3'}, {no:8, name:'PS4', categoryNo:'4'}, {no:9, name:'トマト', categoryNo:'1'}, {no:10, name:'チキン', categoryNo:'2'}, {no:11, name:'いちご', categoryNo:'3'}, {no:12, name:'電子レンジ', categoryNo:'4'}, {no:13, name:'じゃがいも', categoryNo:'1'}, {no:14, name:'ポーク', categoryNo:'2'}, {no:15, name:'ぶどう', categoryNo:'3'}, {no:16, name:'セガサターン', categoryNo:'4'}, ]; var vm = new Vue({ el: "#main", data: { filterItems: items.concat(), category:[ {no:1, name:'野菜'}, {no:2, name:'肉'}, {no:3, name:'果物'}, {no:4, name:'その他'}, ], selectCategory: '' }, watch: { selectCategory: function(newValue) { var self = this; // 初期化 self.filterItems = items.concat(); // フィルター if(newValue != '') { self.filterItems = items.filter(function (item) { return (newValue == item.categoryNo); }); } } } });
解説
リストを表示するとこは以下参照
今回の記事のミソは、watch
を使ってフィルタリングをすることです。
普段のリストでフィルタリングする時には、computed
を使用します。
しかしVue.Draggableではcomputed
を使うと挙動がおかしくなります。
それならv-if
を使ったらどうだと思ったのですが、これまた挙動不審(並び順が初期化される)ので、watch
を使うしかないなとなりました。
watch
は対象のデータを監視して、変更があったら動作します。
https://jp.vuejs.org/v2/guide/computed.html#ウォッチャ
これを利用して、プルダウンが選択されたらv-model
でselectCategory
を変更して、watch
を起動します。
watch
が動作するとfilter
が、カテゴリーに属するアイテムだけをリストに残します。
この時に注意すべきは、filter
するリストが初期の全てアイテムを保有していることです。
以下ソースコードを参照
watch: { selectCategory: function(newValue) { var self = this; // 初期化 self.filterItems = items.concat(); // フィルター if(newValue != '') { self.filterItems = items.filter(function (item) { return (newValue == item.categoryNo); }); } } }
いかがでしょうか?
今日はこの辺でー