非同期通信で検索機能を実装する
簡単な流れ
検索ボタンを押す→サーバー側の任意のアクションへリクエストを投げる→DBから任意の値をとってくる→レスポンスとしてjsonデータをフロント側に返す→フロントはそれを元にビューを作成
使用したもの
- user.js
- UserController.php
- user/index.blade.php
- web.php
step1 フロント側
1. イベントの起点を決める
検索フォームとクリックイベントの起点となるボタンを記述
index.blade.php
<div class="search-wrapper col-sm-4">
<div class="user-search-form">
{{ Form::text('search_name', null, ['id' => 'search_name', 'class' => 'form-control shadow', 'placeholder' => 'ユーザーを検索する']) }}
{{ Form::button('<i class="fa fa-search" aria-hidden="true"></i>', ['class' => 'btn search-icon', 'type' => 'button']) }}
</div>
</div>
ポイント
- フォームファサードを使うが
Form::open
の記述はいらない - buttonタグのtypeは
button
にしないと遷移が走ってしまう -
search-icon
がイベントの起点
2.ajaxを走らせる
検索ボタンを押下後にサーバーサイドにリクエストを送れるようにする
$('.user-search-form .search-icon').on('click', function () {
$('.user-table tbody').empty(); //もともとある要素を空にする
$('.search-null').remove(); //検索結果が0のときのテキストを消す
let userName = $('#search_name').val(); //検索ワードを取得
if (!userName) {
return false;
} //ガード節で検索ワードが空の時、ここで処理を止めて何もビューに出さない
$.ajax({
type: 'GET',
url: '/user/index/' + userName, //後述するweb.phpのURLと同じ形にする
data: {
'search_name': userName, //ここはサーバーに贈りたい情報。今回は検索ファームのバリューを送りたい。
},
dataType: 'json', //json形式で受け取る
beforeSend: function () {
$('.loading').removeClass('display-none');
} //通信中の処理をここで記載。今回はぐるぐるさせるためにcssでスタイルを消す。
}).done(function (data) {
//以下は後述
ポイント
- dataTypeはjson
- 今回は表示させるだけなのでget通信
- beforeSendは無くても良い
これでサーバーへ非同期でデータが渡せる
step2 サーバー側
1.コントローラーを呼ぶ
まず、ajaxでurlを設定した通りにweb.phpでルーティングを構築する
Route::get('/user/index/{name}', 'UserController@getUsersBySearchName'); // url: '/user/index/' + userNameと同じ
これでajaxが走ったときにUserコントローラーのgetUsersBySearchNameアクション
が呼ばれる
2.DBから値を取得しjsonでフロントへ返却
URLのパラメーターを引数にUserモデルから任意の値を取得する
UserController.php
public function getUsersBySearchName($userName)
{
$users = $this->user->where('name', 'like', '%' . $userName . '%')->withCount('items')->orderBy('items_count', 'desc')->get(); //出品数もほしいため、withCountでitemテーブルのレコード数も取得
return response()->json($users);
}
ポイント
- 返り値は必ずjsonデータ
step3 フロント側
1.サーバーから受け取った値をビューに表示
ajax通信が成功したときの処理としてjsonデータをビューに表示させる。
dataにはサーバーから受け取った値がjson形式で入っている
}).done(function (data) { //ajaxが成功したときの処理
$('.loading').addClass('display-none'); //通信中のぐるぐるを消す
let html = '';
$.each(data, function (index, value) { //dataの中身からvalueを取り出す
//ここの記述はリファクタ可能
let id = value.id;
let name = value.name;
let avatar = value.avatar;
let itemsCount = value.items_count;
// 1ユーザー情報のビューテンプレートを作成
html = `
<tr class="user-list">
<td class="col-xs-2"><img src="${avatar}" class="rounded-circle user-avatar"></td> //${}で変数展開
<td class="col-xs-3">${name}</td>
<td class="col-xs-2">${itemsCount}</td>
<td class="col-xs-5"><a class="btn btn-info" href="/user/${id}">詳細</a></td>
</tr>
`
})
$('.user-table tbody').append(html); //できあがったテンプレートをビューに追加
// 検索結果がなかったときの処理
if (data.length === 0) {
$('.user-index-wrapper').after('<p class="text-center mt-5 search-null">ユーザーが見つかりません</p>');
}
}).fail(function () {
//ajax通信がエラーのときの処理
console.log('どんまい!');
})
ポイント
- console.log(data)でdataの中身を確認する
- 検証ツールのnetwork欄でajaxの情報が確認できる
- ドット記法でdataの中身を取り出せる
- eachを使って各テンプレートに変数を代入する
- それをビューにappendさせる(ちなみに上記コードよりまとめたあとに一つの変数としてappendしたほうがよい)
ちゃんとビューに表示されていれば完成!