目次
環境
vue.js : 2.5.8
Vue.Draggable: 2.15.0
はじめに
Vue.Draggableを使いながらリストをフィルタする機能が欲しいと思いました。
しかし、Vue.Draggableの特性と言いますか、制限のようなものでcomputedが使用できません。
そこで別のやり方で実装しました。
デモ
ソース
■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/sortablejs@1.7.0/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);
});
}
}
}
});
解説
リストを表示するとこは以下参照
https://www.kabanoki.net/1712
今回の記事のミソは、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);
});
}
}
}
いかがでしょうか?
今日はこの辺でー