Vue.Draggableでフィルタリングされたリストを使用する

2018年3月14日

環境

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);
                });
            }
        }
    }
});

 

 

解説

リストを表示するとこは以下参照

Vue.jsでドラッグ&ドロップするなら「Vue.Draggable」がおすすめ

 

今回の記事のミソは、watchを使ってフィルタリングをすることです。

普段のリストでフィルタリングする時には、computedを使用します。
しかしVue.Draggableではcomputedを使うと挙動がおかしくなります。

それならv-ifを使ったらどうだと思ったのですが、これまた挙動不審(並び順が初期化される)ので、watchを使うしかないなとなりました。

watchは対象のデータを監視して、変更があったら動作します。
https://jp.vuejs.org/v2/guide/computed.html#ウォッチャ

 

これを利用して、プルダウンが選択されたらv-modelselectCategoryを変更して、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);
      });
    }
  }
}

 

いかがでしょうか?

今日はこの辺でー

 

 

  • この記事を書いた人

カバノキ

印刷会社のWEB部隊に所属してます。 WEB制作に携わってから、もう時期10年になります。 普段の業務では、PHPをメインにサーバーサイドの言語を扱っています。 最近のお気に入りはJavascriptです。 Vue.jsを狂喜乱舞しながら、社内に布教中です。

-vue.js
-, , , , , , ,