すぐできる!Laravelとselect2をAjaxで連携させる方法

さてさて、最近このブログではVueは基本としつつも「jQueryの優秀なプラグインはどんどん使っていこう」という流れがあります。

というのも、最近のフロントエンド業界はトランスパイル、ビルドなど複雑になりすぎてしまって「それってホントに効率的なのかな???」という疑問がなくもないからです。

※ 特にnpm run watchの自動ビルドは、ブラウザで確認するまでに多少時間がかかります。なので、開発テンポが悪くなるんであまり好きじゃないんです・・・😣

そして、jQueryのプラグインの中で気に入っているのがselect2です。

select2は通常のセレクトボックスに検索機能を追加することができるパッケージで、特に選択肢がたくさんある場合はとても便利です。

こんなカンジです。
↓↓↓

そこで!

今回はこのselect2を、Ajaxを通してLaravelと連携させる方法をご紹介したいと思います。(最後に実際に開発したソースコードをダウンロードできます)

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

開発環境: Laravel 6.x

やりたいこと

今回開発する内容は次のとおりです。

  • usersテーブルにあるデータをselect2で選択できるようにする
  • ユーザーデータはAjaxで取得する
  • 一気にデータ取得するとレスポンスが悪くなるので、1回につき10件ずつ取得
  • Ajaxで取得したデータはJavaScriptの中で加工する
  • (おまけで)日本語化、クリアを可能にする

では、実際にやってみましょう!

※ なお、DBに以下のようなユーザーデータがあることが前提です。もしまだ用意していない方は、Laravel6.0でログイン機能を使う方法Laravel 6以上)か【Laravel5.6】インストール直後にやること3点(それより昔のバージョン)を参考にしてみてください。

ルートをつくる

まずは、routes/web.phpを開いて次のルートを追加してください。

Route::get('select2_ajax', 'HomeController@select2_ajax');
Route::get('ajax/user', 'Ajax\UserController@index');

上がブラウザでアクセスするページで、下がAjaxでデータ取得(検索)するものになります。

コントローラーをつくる

続いてはコントローラーです。
今回は後で管理しやすいように、2つのコントローラーに分けます。

以下のコマンドを実行してください。(すでに存在している場合は省略してもOKです)

php artisan make:controller HomeController

中にselect2_ajax()を追加してください。

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;

class HomeController extends Controller
{
    // 省略
    public function select2_ajax() {

        return view('select2_ajax');

    }

続いてAjax部分のコントローラーです。(今回はユーザーを選択するセレクトボックスなのでUserControllerとしていますが、状況に応じて名前は変更してください)

php artisan make:controller Ajax\\UserController

中身はこうなります。

<?php

namespace App\Http\Controllers\Ajax;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request) {

        $query = \App\User::query();

        if($request->filled('q')) {

            $keywords = explode(' ', trim(mb_convert_kana($request->q, 's')));

            foreach($keywords as $keyword) {

                $query->where('name', 'LIKE', '%'. $keyword .'%');

            }

        }

        $per_page = 10;
        return $query->paginate($per_page);

    }
}

まず、select2から送られてくるqというパラメータが検索キーワードになっているので、これを使ってusersのデータ検索をしています。

※ 今回はnameのみでの検索ですが、お好みでメールアドレスや電話番号も含めて検索してもいいでしょう。

さらに、$per_pageが1回のアクセスごとに何件取得するかという数字になっていますので、ここもお好みで変更してください。

ビューをつくる

では、最後にビューを作成します。

resources/views/select2_ajax.blade.phpというファイルを作成して以下の内容を追加してください。

<html>
<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/css/select2.min.css">
</head>
<body>
    <div>
        <select style="width:250px;" class="select2-ajax"></select>
    </div>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.min.js"></script>
    <script>

        // ページが読み込まれたら実行
        $(() => {

            $('.select2-ajax').select2({
                ajax: {
                    url: '/ajax/user',
                    dataType: 'json',
                    processResults(response) {  // データをselect2向けに加工

                        let options = [];

                        response.data.forEach((user) => {

                            options.push({
                                id: user.id,
                                text: user.name
                            });

                        });

                        return {
                            results: options,
                            pagination: {
                                more: (response.next_page_url !== null)  // 次ページがあるかどうか
                            }
                        };

                    }
                }
            });

        });

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

まず、select2を使うために必要な作業は次のとおりです。

  • cdn で jQuery と select2 を読み込む
  • <select> 〜 </select> タグをつくる
  • select2() メソッドで、select2を起動

そしてselect2Ajaxを使うためには、パラメータ内に以下3つのオプション値を含んだajaxパラメータを指定することになります。

  • url ・・・ Ajaxでデータ取得するページのURL
  • dataType ・・・ データタイプ。省略するとjsonになるみたいです。
  • processResults ・・・ Ajaxで取得したデータを加工するメソッド

ここで一番重要なのがprocessResultsです。

この中でLaravelからAjaxを通して提供されるデータをselect2向けに加工しています。(つまり、Laravel側でid & textのデータを用意するならここは必要ありません)

また、paginationパラメータのmoreは、「まだ残りのデータが存在しているかどうか」という意味で、まだ残っているならselect2はページ番号を増やして再度AjaxのURLにアクセスをすることになります。

※ なお、select2Laravelもページ番号にはpageというパラメータを使っているので、この部分は加工する必要はありません。

おまけ

では、せっかくここまでselect2でコンテンツを作ってきたので、おまけとして次の2つもやってみましょう。

  • 日本語化
  • 選択されたものをクリア可能にする

まず日本語化するには、専用のcdnが用意されているのでそれを追加で読み込みます。

<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/select2.min.js"></script>

<!-- ここを追加 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.10/js/i18n/ja.js"></script>

そして、select2のオプションにlanguageパラメータを追加すればOKです。

$('.select2-ajax').select2({

    // 省略

    language: 'ja' // 日本語化
});

続いてクリアを可能にするには、オプションのallowClearplaceholderを設定します。

$('.select2-ajax').select2({

    // 省略

    allowClear: true,
    placeholder: ''
});

一見allowClearだけで良さそうなものですが、実はplaceholderとペアになっているらしく単体ではうまくいきません。

このオプションをつけると以下のようにクリアマークが表示されるようになります。

テストしてみる

では、今回開発したコンテンツを実際にテストしてみましょう。

はい!うまくいきました😊✨

ダウンロードする

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

※ ただし、usersテーブルのデータはご自身で用意していただく必要があります。

Laravelとselect2をAjaxで連携

おわりに

ということで、今回はLaravelselect2Ajaxで連携させてみました。

サイト運営を長く続けていると、どうしてもデータが増えてしまいパフォーマンスが落ちてしまうことはよくありますので、このテクニックを使ってより高速に、より使いやすい選択機能を作ってみてはいかがでしょうか。

ちなみに、私がメインで使っているVueと連携させることもできますので、もし興味がある方は過去記事のすぐできる!VueとjQueryパッケージを連携させる方法を参考にしてみてくださいね。

ではでは〜!

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