忘れないように記録しとこ

カバの樹

Vue.js 3を使ってTableをカスタマイズしていく(フィルター)

2023年1月27日

はじめに

Vue.js 3系を使ってテーブルを色々カスタマイズして行こうと思います。

前回に引き続き、条件分岐でテーブルに表示する項目をフィルターする機能を実装していきます。

関連
Vue.js 3を使ってTableをカスタマイズしていく(transition-groupを設定する)

Vue.js 3系を使ってテーブルを色々カスタマイズして行こうと思います。
前回に引き続き、テーブルのデータを追加したり、削除した時に、 を使って、アニメーション追加していきます。

続きを見る

 

【動画サイズ:205KB】

 

環境

この記事は、以下の管理人の検証環境にて記事にしています。

vue.js 3.2.26

 

完成ソースコード

サンプルはBootstrapを使用しています。

Bootstrap

<!-- bootstrap -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

 

HTML

<div id="app" class="container mt-5">
  <div class="row">
    <div class="col-9 row">
      <div class="col">
        <div class="form-group">
          <lable for="search">キーワード検索:</lable>
          <input type="text" id="search" class="form-control" v-model="search" autocomplete="off">
        </div>
      </div>
      <div class="col">
        <div class="form-group">
          <lable for="cateogry">カテゴリー:</lable>
          <select id="cateogry" class="form-select" v-model="selectCategory">
            <option value="">カテゴリーを選択</option>
            <option v-for="category in categories" :value="category">{{category}}</option>
          </select>
        </div>
      </div>
    </div>
    <div class="col text-end">
      <button class="btn btn-primary my-3" @click="doAdd">リスト追加</button>
    </div>
  </div>
  <table class="table table-bordered">
    <thead>
      <tr>
        <th v-for="(label, key) in header" :key="key">{{label}}</th>
        <th></th>
      </tr>
    </thead>
    <tbody is="vue:transition-group" name="list" tag="tbody">
      <tr v-for="(item, index) in getItems" :key="item.no">
        <td v-for="(label, key) in header" :key="'td'+key+item.no">{{item[key]}}</td>
        <td><button class="btn btn-danger" @click="doRemove(index)">削除</button></td>
      </tr>
    </tbody>
  </table>
</div>

 

Javascript

const App = {
  data() {
    return {
      header: {no:'No', name:'Name', email:'E-Mail', category:'Category'},
      items:[
        {no:1, name:'Daiki', email:'daiki@hoge.net', category:'管理者'},
        {no:2, name:'Naoki', email:'naoki@hoge.net', category:'一般'},
        {no:3, name:'Yuki', email:'yuki@hoge.net', category:'一般'},
        {no:4, name:'Aoi', email:'aoi@hoge.net', category:'グループ'},
        {no:5, name:'Hnako', email:'hanako@hoge.net', category:'グループ'},
        {no:6, name:'Momo', email:'momo@hoge.net', category:'企業'},
        {no:7, name:'Taro', email:'taro@hoge.net', category:'企業'},
        {no:8, name:'Shiori', email:'siori@hoge.net', category:'一般'},
        {no:9, name:'Jiro', email:'jiro@hoge.net', category:'一般'},
        {no:10, name:'Sigeru', email:'sigeru@hoge.net', category:'企業'},
      ],
      maxNo: 11,
      categories: [
        '管理者',
        '一般',
        'グループ',
        '企業'
      ],
      search: '',
      selectCategory: '',
    }
  },
  methods: {
    doAdd: function(){
      this.items.push({
        no: this.maxNo, 
        name:'Add User '+this.maxNo, 
        email:'adduser@hoge.net',
        category: 2
      });
      this.maxNo = this.maxNo + 1;
    },
    doRemove: function(index){
      this.items.splice(index, 1);
    }
  },
  computed: {
    getItems: function(){
      let self = this;
      return this.items.filter(function(item){
        return (
          (String(item.no).indexOf(self.search) !== -1)
          || (String(item.name).indexOf(self.search) !== -1)
          || (String(item.email).indexOf(self.search) !== -1)
        ) && (
          (String(item.category).indexOf(String(self.selectCategory)) !== -1)
        );
      });
    },
  },
}
Vue.createApp(App).mount('#app');

 

CSS

.list-enter-active,
.list-leave-active {
  transition: all 1s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

 

サンプル

今回のソースを実際に触って確認できるようにデモを用意しました。

サンプルはBootstrapを使用しています。

 

サーチテキストでフィルターする

 

step.1 サーチテキストのセッターを設置する

サーチテキストを入力した時に「search」に入力したテキストを保持します。

data() {
  return {
~~~
    search: '',
~~~
}

 

step.2 テキスト入力のセッターを設置する

「v-model」に「search」を設定します。
これでテキストを入力した時に、セッターにデータを保持することができます。

<input type="text" id="search" class="form-control" v-model="search" autocomplete="off">

 

step.3 サーチテキストでリストをフィルターする

Step2で保持したテキストを使って、テーブルのリストをフィルタします。
「computed」で「getItems」を作成して、リストの配列を返します。
その際に「filter」を使って、サーチテキストの内容を持つリストだけを返すようにします。
「indexOf」を使って比較をします。

computed: {
  getItems: function(){
    let self = this;
    return this.items.filter(function(item){
      return (
        (String(item.no).indexOf(self.search) !== -1)
        || (String(item.name).indexOf(self.search) !== -1)
        || (String(item.email).indexOf(self.search) !== -1)
      );
    });
  },
}

 

 

カテゴリーでフィルターする

 

step.1 カテゴリーのマスターとセッターを設置する

dataに「categories」という名前でカテゴリーマスターの配列を設定する。
選択したカテゴリーを保持するための「selectCategory」も用意する。

data() {
  return {
~~~~
    categories: [
      '管理者',
      '一般',
      'グループ',
      '企業'
    ],
    selectCategory: '',
  }
}

 

step.2 カテゴリーのセレクトを追加する

「v-for」で「categories」をループで回して「<option>」を複製して表示する。
選択されたカテゴリーは「v-model」を通して保持します。

<select id="cateogry" class="form-select" v-model="selectCategory">
  <option value="">カテゴリーを選択</option>
  <option v-for="category in categories" :value="category">{{category}}</option>
</select>

 

step.3 選択したカテゴリーでテーブルのリストをフィルターする

「computed」で「getItems」を使ってテーブルのリストのデータとなる配列を返します。
その際に「filter」を使って、選択されたカテゴリーとリストのカテゴリーが一致するものだけを返すようにします。

computed: {
  getItems: function(){
    let self = this;
      return this.items.filter(function(item){
        return (
          (String(item.category).indexOf(String(self.selectCategory)) !== -1)
        );
      });
  },
},

 

step.4 リストにカテゴリーを追加する

前回から使っている「items」のリスト要素に「category」というkeyで、カテゴリーを持たせます。
このカテゴリーを元に、Step3のフィルターが動作します。

data() {
  return {
~~~
    items:[
      {no:1, name:'Daiki', email:'daiki@hoge.net', category:'管理者'},
      {no:2, name:'Naoki', email:'naoki@hoge.net', category:'一般'},
      {no:3, name:'Yuki', email:'yuki@hoge.net', category:'一般'},
      {no:4, name:'Aoi', email:'aoi@hoge.net', category:'グループ'},
      {no:5, name:'Hnako', email:'hanako@hoge.net', category:'グループ'},
      {no:6, name:'Momo', email:'momo@hoge.net', category:'企業'},
      {no:7, name:'Taro', email:'taro@hoge.net', category:'企業'},
      {no:8, name:'Shiori', email:'siori@hoge.net', category:'一般'},
      {no:9, name:'Jiro', email:'jiro@hoge.net', category:'一般'},
      {no:10, name:'Sigeru', email:'sigeru@hoge.net', category:'企業'},
    ],
~~~
  }
},

 

さいごに

次回はテーブルの行をドラッグ移動できるようにします。

 

その他のまとめは下記よりご覧ください。

まとめ
Vue.js 3を使ってTableをカスタマイズしていく(まとめ)

Vue.js 3系を使ってテーブルを色々カスタマイズして行こうと思います。

続きを見る

 

  • B!