Vue.jsのフィルターを使ってもcheckedを維持する

2017年11月21日

環境

vue.js :

 

はじめに

最近Vue.jsの記事を書く機会増えてきました。

今回は、Vue.jsのリストフィルタを使った時に、チェックボックスのチェックが外れてしまうのに対応します。

 

checkedの維持

Vue

new Vue({
        el: '#app',
        data:
            {
                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'},
                ],
                categoryItems: [
                  {no:1, name:'野菜'},
                  {no:2, name:'肉'},
                  {no:3, name:'果物'},
                  {no:4, name:'その他'},
                ],
                search: '',
                selectCategory:'',
            },
        methods:{
            setChecked: function(key, event) {
                var self = this;
                for(var i in self.items) {
                    if(self.items[i]['no'] == event.target.value) {
                        if(event.target.checked == true) {
                            self.items[i][key] = 1;
                        }
                        else {
                            self.items[i][key] = 0;
                        }
                        break;
                    }
                }
            },
            setValue: function(key, index, event){
                var self = this;
                self.items[index][key] = event.target.value;
            },
            defChecked: function (item){
                if(item.checked == 1)
                    return true;
                else
                    return false;
            }
        },
        computed: {
            getItems: {
                get: function () {
                    var self = this;
                    return self.items.filter(function (item) {
                        return (
                            (item.name.indexOf(self.search) !== -1)

                            && (item.categoryNo.indexOf(self.selectCategory) !== -1)
                        );
                    });
                },
                set: function (v) {
                    this.items = v;
                }
            },
            getCategoryItems: {
                get: function () {
                    var self = this;
                    return self.categoryItems;
                },
                set: function (v) {
                    this.items = v;
                }
            },
        },
    });

 

HTML

<div id="app" class="content" style="padding:40px">
  <div class=row>
    <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
      <div class="checkbox" v-for="(item, index) in getItems">
        <label>
          <input type="checkbox" 
                 v-on:click="setChecked('checked', $event)"
                 v-bind:value="item.no"
                 v-bind:checked="defChecked(item)">
          {{item.name}}
        </label>
      </div>
    </div>
    <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
        <div class="form-group">
          <label for="exampleInputEmail1">テキスト絞込み</label>
          <input type="text" v-model="search" class="form-control" id="exampleInputEmail1" placeholder="Email">
        </div>
        <div class="form-group">
          <label for="exampleInputEmail1">カテゴリー選択</label>
          <select class="form-control" v-model="selectCategory">
            <option value="">選択</option>
            <option v-for="(item, index) in getCategoryItems"
                    v-bind:value="item.no">{{item.name}}</option>
          </select>
      </div>
    </div>
  </div>
</div>

 

デモ

See the Pen jawYPN by カバの樹 (@kabanoki) on CodePen.0

 

checkedを保持する

Vueでフィルタリングをすると、リストのアイテムが削除されてしまいます。
なので、フィルターを解除するとアイテムが再生成されて、チェックボックスが空の状態になってしまいます。
そこで、以下のソースでcheckedをアイテムに持たせてしまいます。

Vue

setChecked: function(key, event) {
var self = this;
for(var i in self.items) {
   if(self.items[i]['no'] == event.target.value) {
     if(event.target.checked == true) {
        self.items[i][key] = 1;
     }
     else {
        self.items[i][key] = 0;
     }
     break;
   }
 }
}

 

HTML

v-on:click="setChecked('checked', $event)"

 

チェックを反映させる

checkedをアイテムに記録できたら、以下のソースで再生成時にcheckedを反映させます。

Vue

setChecked: function(key, event) {
  var self = this;
  for(var i in self.items) {
    if(self.items[i]['no'] == event.target.value) {
       if(event.target.checked == true) {
          self.items[i][key] = 1;
       }
       else {
          self.items[i][key] = 0;
       }
       break;
    }
  }
}

 

HTML

v-bind:checked="defChecked(item)"

どうでしょうか?

今日はこの辺でー

  • この記事を書いた人

カバノキ

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

-vue.js
-, , ,