Vue + DataTableにチェックボックスで複数削除の機能をつける

さてさて。最近になってですが、とあるブログで見た内容を思い出すことがありました。

その内容は要約すると、「VueやReactはすごい!でもちょっとしたものならjQueryのプラグインを使った方が早いよ。」といったものでした。

なぜこれを思い出したかというと、有名jQueryプラグインの「DataTable」をがとても便利だと再認識したからです。

そして、今回はそんなDataTableのユーザビリティを向上させるカスタマイズ法をご紹介したいと思います。

それは、

各行にチェックボックスをつけてデータを複数削除できるようにする機能

です。

つまり、これです。(いわゆるBulk Deleteと呼ばれる機能ですね)

このチェックボックスがあれば、一気にデータ削除できて便利ですし、削除ボタンは1つあればいいので省スペースも実現できると思います。

ということで、今回はこのチェックボックス+複数削除をVueDataTableで連携させて実現してみます。(最後にソースコードをダウンロードできます)

ぜひ皆さんのお役に立てると嬉しいです😊✨

開発環境: Vue 2.6

やりたいこと

具体的に今回実装する機能は次のとおりです。

  • DataTableの各行にチェックボックスをつけて選択できるようにする
  • 選択したデータのIDをVueの変数へ格納できるようにする
  • 「全てをチェック」を使って全選択/全解除が可能
  • チェックの状況によって、削除ボタンを表示/非表示
  • 削除ボタンが押されたら特定のメソッドを実行する

では、順を追って見ていきましょう!

環境を整える

まずは、今回必要になるパッケージやCSSを読み込むのですが、DataTableは本家が用意してくれているこちらのCDNページから(Bootstrap 4向け)を使うことにします。

<html>
<head>
    <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css">
</head>
<body>
    <div id="app" class="container">

        <!-- ここにDataTableをつくる -->

    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
    <script src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>
    <script>

        new Vue({
            el: '#app'
        });

    </script>
</body>
</html>

なお、Vueの基本形も同時につくっておきました。

DataTableを表示する

では、メインとなるDataTableを表示してみましょう。

まずはHTMLコードです。

<div id="app" class="container">
    <table id="table" class="table table-striped table-bordered table-sm">
        <thead class="thead-dark">
        <tr>
            <th>
                <label>
                    <input id="all_check" type="checkbox"> 全てをチェック
                </label>
            </th>
            <th>ID</th>
            <th>名前</th>
            <th>年齢</th>
        </tr>
        </thead>
        <tbody></tbody>
    </table>
</div>

ここで大事なのは後で利用するテーブルのidとチェックボックスの全選択/解除をするためのチェックボックスです。

次に、ページが読み込まれたら実行されるmounted()に以下のコードを追加します。

new Vue({
    el: '#app',
    mounted() {

        $('#table').DataTable({
            data: [
                { id: 1, name: '山田太郎', age: 25},
                { id: 2, name: '佐藤次郎', age: 33},
                { id: 3, name: '田中三郎', age: 15},
            ],
            columns: [
                {
                    data: 'id',
                    render: (id) => {

                        return '<input class="delete_check" type="checkbox" value="'+ id +'">';

                    },
                    orderable: false
                },
                { data: 'id' },
                { data: 'name' },
                { data: 'age' },
            ],
            order: [[ 1, 'asc' ]],
            language: {
                url: 'https://cdn.datatables.net/plug-ins/1.10.20/i18n/Japanese.json'
            }

            // ここでその他オプションを設定できます

        });

    }
});

ここで重要なのは、columns内です。

DataTableではrenderを指定することで動的に表示内容を変更することができます。なので、この場所で後でセレクタとして使うclass="delete_check"を指定し、valueに各IDをセットします。

そしてもう一つ、orderの部分ですが、この記述がないと0番目、つまりチェックボックスの列がデフォルトで並べ替えの対象になってしまうので、その隣の1番目(ゼロから始まる2番目の数字)を指定しています。

あとは、DataTableの基本的な内容ですので、こちらのページ(英語)で確認するといいでしょう。(いつかこのブログでオプションもまとめたいと思います)

これを実行すると以下のようになります。

※ これだけのコードでここまで実現できるのはやっぱり開発者としては嬉しいですね。ちなみに、オプションを使えばAjaxでのデータ通信も可能です。詳しくは、LaravelとDataTable.jsをAjaxで連携させる方法をご覧ください😊✨

チェックボックスの全選択/解除ができるようにする

では、「全てをチェック」のすぐ横にあるチェックボックスがクリックされたら、全選択/解除ができるようにしていきましょう。

まずはチェックボックスの値が変更されたときのイベントcheckAllを準備します。(ちなみに、Vueでは変数が必要ない場合は()を省略できます)

<input id="all_check" type="checkbox" @change="checkAll"> 全てをチェック

そして、Vueの中にmethodsをつくり、その中にcheckAll()を用意します。

new Vue({
    el: '#app',
    methods: {
        checkAll(e) {

            const checked = $(e.target).prop('checked'); // 全選択/解除どちらか

            $('.delete_check').each((i, element) => { // 全てのチェックボックスの値を変更

                $(element).prop('checked', checked).change();

            });

        }
    },

    // 省略

});

checkAll()の中身はjQueryのみのコードになっています。(個人的には少し懐かしいです😊)

なお、このコードの中でchange()をつけているのは、次の項目でつくるchangeイベントで起動するためです。

$(element).prop('checked', checked).change(); // changeイベントを送出

これで、全選択と解除ができるようになりました。

チェックされたIDをVueと連携させる

では、各行のチェックボックスのtruefalseが変更になった時に実行する部分をつくっていきます。

チェックされたIDを格納&取得するコードをつくる

まずはチェックされたIDに関する部分です。

new Vue({
    el: '#app',
    data: {
        checkedIds: []
    },
    methods: {

        // 省略

        getCheckedIds() {  // チェックされているIDを取得

            let ids = [];

            $('.delete_check:checked').each((i, element) => {

                let id = $(element).val();
                ids.push(id);

            });

            return ids;

        }
    },

    // 省略

});

この中では、まずdatacheckedIdsという「今チェックされているID」を格納する変数を用意します。

そして、その変数のために「今チェックされているID」を取得するメソッドgetCheckedIds()をつくります。

チェックボックスが変更されたときのchangeイベントをつくる

続いて、チェックボックスのtruefalseが変更された時に実行されるchangeイベントをつくります。

new Vue({

    // 省略

    mounted() {

        // 省略

        $(document).on('change', '.delete_check', () => {

            this.checkedIds = this.getCheckedIds();

            if(this.checkedIds.length === 0) {

                $('#all_check').prop('checked', false);

            }

        });

    }
});

ここで重要なのが、以下のようにセレクタを直接指定していないところです。

// これはうまく動きません

$('.delete_check').on('change', () => {

    // 省略

});

なぜならこの書き方は「すでに存在している、セレクタが”.delete_check”のもの」にイベントをつけるという意味だからです。

つまり、DataTableVuev-forのように後から要素がつくられる場合は、イベントをつけることができないわけです。

こんな場合はdocument本体にイベントをつける書き方にすると、後から作成される要素であってもイベントが起動するようになります。

$(document).on('change', '.delete_check', () => {

    // 省略

});

※ VueとjQueryの連携をする場合はこのテクニックはとても役に立ちます😊

また、このchangeイベントの中では先ほどのgetCheckedIds()を使ってcheckIdsを更新し、さらにチェックされているものがなくなっている場合は、「全てをチェック」のチェックボックスも自動で解除するようにしています。

削除ボタンをつくる

では、最後にいづれかのチェックボックスがtrueになった時に削除ボタンを表示できるようにしてみましょう(チェックされてなければ非表示にします)

まずはHTML側にボタンを用意します。

<div id="app" class="container">

    <!-- 省略 -->

    <div v-if="hasCheckedIds">
        <button type="button" class="btn btn-primary" @click="onDelete">削除する</button>
    </div>
</div>

そして、この中で指定したhasCheckedIdscomputedに作成します。

new Vue({

    // 省略

    computed: {
        hasCheckedIds() {   // チェックされたものがあるかどうか

            return (this.checkedIds.length);

        }
    },

    // 省略

});

これでチェックの有無によって削除ボタンの表示/非表示が切り替わるようになりました。

そして、同じくこのボタンをクリックしたときに実行するonDeleteもつくっておきましょう。

new Vue({

    // 省略

    methods: {

        // 省略

        onDelete() {

            const params = {
                checked_ids: this.checkedIds
            };
            console.log(params)

            // ここでaxiosなどでAjax送信して削除
            // axios.post(url, params)
            //     .then((response) => {
            //
            //
            //
            //     });

        }
    },
    
    // 省略

});

はい!これで全て完了です。

お疲れ様でした😊✨

テストしてみる

では、今回のコードを実際に動かしてテストしてみます。

うまくいきました!

ダウンロードする

今回実際に開発した内容を以下からダウンロードすることができます。

※ パッケージは全てCDN経由なので展開したらすぐ実行できますよ!

Vue + DataTableにチェックボックスで複数削除の機能をつける

おわりに

ということで今回は、有名jQueryプラグインのDataTableに関する話題をお届けしました。

ReactAngularVueなどのリアクティブなパッケージが登場したしたことでjQueryは昔ほどの人気ではなくなっているとは思いますが、とはいえやはり開発に有効な手段であることに変わりはないな、と再認識しました。

特にに今のところBootstrapjQueryが必須となっていますので、そうなるとDataTableのようなプラグインも頭にいれておいて損はしないのではないと思います。

また、VuejQueryの連携は少しテクニックが必要ですが覚える内容はそれほど多くないですし、それほど手間もかからないです。

ぜひ皆さんも「適材適所」な開発をしてみてくださいね。

ではでは〜!

この記事が役立ちましたらシェアお願いします😊✨