Vueでポップアップする画像つきセレクトボックスをつくる(DL可)

こんにちは❗フリーランス・エンジニアの 九保すこひ です。

さてさて、先日とあるオンライン・ショッピングサイトにスマホで訪問したのですが、注文をするときに「こうだったらいいのにな❗」と思うことがありました。

それは・・・

セレクトボックスに画像がほしい

というものでした。

・・・というのも、その注文では5〜6個の商品を個別に選ぶことができたんですが、選ぶときに商品名だけなので「うーん、どの商品かイメージできない😫」となったからなんですね。

(しかも、スマホだったので別ページに移動すると選択した商品がクリアされてしまうわけです)

そこで!

今回はVueを使って「ポップアップする画像つきセレクトボックス」をつくってみたいと思います。

ぜひ皆さんのお役に立てると嬉しいです😊✨
(最後に今回実際に開発したソースコード一式をダウンロードできますよ)

「ステイホームなので、
YouTubeばかり見ています👍」

開発環境: Laravel 7.x、Vue 2.6、jQuery 3.4.1、Bootstrap 4.4.1

この記事を見たらできること

以下のような画像つきのセレクトボックスをつくることができます。
なお、「選択を解除」をクリックすると選択がクリアされるようにします。

デモページはこちら

ではやっていきましょう❗

HTML部分をつくる

まず基本となるHTMLを用意します。

<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div id="app" class="p-3">

        <!-- セレクトボックス(実際はボタン) ・・・ ① -->
        <button type="button" class="btn border-secondary" data-toggle="modal" data-target="#image-select-modal">
            <div v-if="!selectedItem">選択してください ▼</div>
            <div v-else>
                <img :src="selectedItem.thumbnailUrl" style="height:30px;">
                <span class="mr-1" v-text="selectedItem.title"></span>
            </div>
        </button>

        <!-- ポップアップ部分(モーダル) ・・・ ② -->
        <div class="modal fade" id="image-select-modal">
            <div class="modal-dialog modal-dialog-centered">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title">選択してください</h5>
                        <button type="button" class="close" data-dismiss="modal">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div id="modal-body" ref="modal-body" class="modal-body p-0" style="width:100%;overflow:auto;">
                        <table class="table table-striped">
                            <tr v-for="item in items"
                                :id="'item-'+ item.id"
                                style="cursor:pointer;"
                                @click="selectItem(item)">
                                <td class="p-3 align-top">
                                    <img :src="item.thumbnailUrl">
                                </td>
                                <td class="pt-3 pr-3 align-top" style="width:100%;">
                                    <h5 v-text="item.title"></h5>
                                    <p style="white-space:pre-wrap;" class="text-secondary" v-html="item.description"></p>
                                </td>
                            </tr>
                        </table>
                    </div>
                    <div class="modal-footer">
                        <a href="#" class="modal-default-button" @click.prevent="clearItem">選択を解除</a>
                    </div>
                </div>
            </div>
        </div>

    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.bundle.min.js"></script>
    <script>

        new Vue({
            el: '#app',
            
            // ここにVueのコード(次の項目で説明します)

        });

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

① セレクトボックス(実際はボタン)

実際は<button>...</button>タグなので、セレクトボックスではありませんが、ここをクリックするとポップアップで画像つきの商品が選択できるようにします。

また、商品が「選択されている or 選択されていない」で表示を切り替えるようにし、選択されたらサムネイル画像と商品名を表示するようにします。

(👇 こんなカンジです)

② ポップアップ(モーダル)部分

ここはBootstrapのモーダル機能を使って実装します。

ただし、このモーダルの中に表示される「商品リスト」はVueでレンダリングしていることに注目してください。

なお、:id="'item-'+ item.id"の部分は例えば「item-1」のようなIDになりますが、これは後ほどスクロール位置を移動させるために使います。

JavaScript部分をつくる

では、JavaScriptの部分をつくっていきましょう。
先ほどつくったVueコードを次のように変更してください。

new Vue({
    el: '#app',
    data: {
        items: [],
        selectedItem: null
    },
    methods: {
        selectItem(item) { // リストから選択 ・・・ ①

            this.selectedItem = item;
            $('#image-select-modal').modal('hide');

        },
        clearItem() { // 選択を解除 ・・・ ②

            this.selectedItem = null;
            $('#image-select-modal').modal('hide');

        }
    },
    mounted() {

        // テスト商品データをつくる ・・・ ③
        let items = [];

        for(let i = 1 ; i <= 25 ; i++) {

            items.push({
                id: i,
                title: 'サンプル商品名 - '+ i,
                description: "サンプル商品説明\nサンプル商品説明\nサンプル商品説明 - "+ i,
                thumbnailUrl: 'https://via.placeholder.com/100/FF5555/FFFFFF?text=item+'+ i
            });

        }

        this.items = items;

        // モーダルの高さを調整 ・・・ ④
        const modalBody = this.$refs['modal-body'];
        modalBody.style.maxHeight = parseInt(window.innerHeight*0.7) +'px';

        // モーダルが表示されたら選択位置へ移動 ・・・ ⑤
        $('#image-select-modal').on('shown.bs.modal', () => {

            const top = (this.selectedItem)
                ? $('#item-'+ this.selectedItem.id).position().top
                : 0;
            $('#modal-body').scrollTop(top);

        });

    }
});

では、ひとつずつ解説していきます。

① リストから選択

ポップアップ表示された商品データが選択されたときに実行されるコードです。

ここで選択されたデータをselectedItemに格納し、結果としてVueが自動的にセレクトボックスの表示を切り替えることになります。(また、自動的にポップアップは閉じます。)

② 選択を解除

選択を解除」リンクがクリックされたときに実行されるコードです。

ここでは、selectedItemnullに戻し、ポップアップを閉じることになります。すると、Vueがセレクトボックスの表示を元に戻すことになります。

③ テスト商品データをつくる

ポップアップする商品リストのテストデータです。
今回はfor()ループで作っていますが、実際にはAjaxなどでデータを取ってくることになると思います。

なお、サムネイル画像はplaceholder.comを利用しています。

④ モーダルの高さを調整

モーダル(ポップアップ)の高さをウィンドウサイズの70%に変更しています。お好みで変更してください。

⑤ モーダルが表示されたら選択位置へ移動

すでに商品が選択されている場合、モーダルを再表示したときにスクロール位置をその商品に合わせるようにしています。(ここでHTML側でつくったIDを使っています)

なお、商品が選択されていない場合はトップ位置になります。

テストしてみる

では実際にテストしてみましょう!
まず表示されたボタンをクリックします。

すると、次のようなポップアップが表示されました。
適当に商品を選択してみます。

選択された商品がボタンの中に表示されました。

選択されました❗
ではもう一度ポップアップさせて、「選択を解除」をクリックしてみましょう。

すると、初期状態に戻りました。

成功です😊✨

教材ソースコードをダウンロードする

今回実際に開発した教材ソースコードを以下からダウンロードできます。

Vueでポップアップする画像つきセレクトボックスをつくる

CDNを使っているので展開したらすぐ実行できますよ👍

おわりに

ということで今回はVueを使った画像つきセレクトボックスをつくってみました。

セレクトボックスに画像がついていると、イメージがしやすいですし、画面移動しなくて良くなるので特にスマホではユーザビリティが向上するんじゃないでしょうか。

また、今回のコードではjQueryVueが共存していますが、こういう使い方もできるんだというのを体験していただけると嬉しいです。

JavaScriptのフレームワークも1つだけに絞った方がいいのはもちろんですが、それも状況によって臨機応変に使えば開発スピードを上げることができると思います。

ぜひそのあたりも注目しながらチャレンジしてみてくださいね。

ではでは〜❗

「そういえば、Bootstrap 5では
jQueryは不要になるらしいですね」

この記事が役立ちましたらシェアお願いします😊✨ by 九保すこひ
また、わかりにくい部分がありましたらお問い合わせからお気軽にご連絡ください。
(また、個人レッスンも承ってます👍)
このエントリーをはてなブックマークに追加       follow us in feedly