LaravelでAjaxのペジネーションの覚え書き

Laravelで大量の配列をページング表示させる必要があった。

しかも、Ajaxを使ってページングを行う必要があった。

いくつかややこしい点があったので、メモメモ。

(完成イメージ)

f:id:aquashine:20200202134132p:plain

■コントローラー

・通常のペジネーションは、ページ数がGETで受けるが、ajaxの場合、POSTでもOK

 

$data = XXXXXXXX;  ←★これが分割表示したい配列とする

$perpage = 10;  ←★1ページ当たりの表示数

$page = $request->input('page'); ←★GETかPOSTで取得した表示させるページ番号

 

//Laravelのcollectヘルパーを使って新しいコネクションを作成

$collection = collect($data);

 

// LengthAwarePaginatorを使う

$items = new LengthAwarePaginator(
            $collection->forPage($page, $perpage),  ←★forPageを使って配列を分割
            count($collection),
            $perpage,
            $page,
            array('path' => $request->url())
        );

//分割したitemsを戻す

return response()->json($items);

 

Ajax

$.ajax({
  type: "POST", ←★POSTでもGETでもOK
  dataType: 'json',
  url: XXXXXX,
  data: {
   'page': page ←★表示させるページ番号
  },
}).done(function(res) {
 //★コントローラーから分割されたitemsを受け取る
});

 

 

基本的にはこれだけでいい。

問題は、Bladeに表示するページングをどうするか。

f:id:aquashine:20200202134132p:plain

 

通常の{{  $hoge->links() }} だとGETでページ遷移してしまう。

結論としては、links()をカスタマイズする必要がある。

 

■追記版のコントローラー

$data = XXXXXXXX;  ←★これが分割表示したい配列とする

$perpage = 10;  ←★1ページ当たりの表示数

$page = $request->input('page'); ←★GETかPOSTで取得した表示させるページ番号

 

//Laravelのcollectヘルパーを使って新しいコネクションを作成

$collection = collect($data);

 

// LengthAwarePaginatorを使う

$items = new LengthAwarePaginator(
            $collection->forPage($page, $perpage),  ←★forPageを使って配列を分割
            count($collection),
            $perpage,
            $page,
            array('path' => $request->url())
        );

 

//ページネーションのHTMLタグをつけて戻す

$res = array();
$res['items'] = $items;
$res['links'] = base64_encode($items->links('ajax_pagination'));//ペジネーションのHTMLタグ
return response()->json($res);

 

 ■viewsの中に、以下のテンプレートを追加

@if ($paginator->lastPage() > 1)
<ul class="pagination">
<li class="page-item {{ ($paginator->currentPage() == 1) ? ' disabled' : 'pointer' }}">
<a class="page-link" data-url="{{ 1 }}">&laquo;</a>
</li>
<li class="page-item {{ ($paginator->currentPage() == 1) ? ' disabled' : 'pointer' }}">
<a class="page-link" data-url="{{ ($paginator->currentPage() == 1) ? 1 : $paginator->currentPage()-1 }}">
<span aria-hidden="true">&lt;</span>
{{-- Previous --}}
</a>
</li>
{{-- デザイン的に入らないのでコメントアウト
@for ($i = 1; $i <= $paginator->lastPage(); $i++)
<li class="page-item {{ ($paginator->currentPage() == $i) ? ' active' : '' }}">
<a class="page-link" data-url="{{ $i) }}">{{ $i }}</a>
</li>
@endfor
--}}
{{-- 上の代わりに現在のページのみ表示 --}}
<li class="page-item active">
<a>{{ $paginator->currentPage() }}</a>
</li>
<li class="page-item {{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : 'pointer' }}">
<a class="page-link" data-url="{{ ($paginator->currentPage() == $paginator->lastPage()) ? $paginator->lastPage() : $paginator->currentPage()+1 }}">
<span aria-hidden="true">&gt;</span>
{{-- Next --}}
</a>
</li>
<li class="page-item {{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : 'pointer' }}">
<a class="page-link" data-url="{{ $paginator->lastPage() }}">&raquo;</a>
</li>
</ul>
@endif

ポイントは、通常のlinks()で生成される<a>タグのhrefを、「data-url」に置き換え、

リンク先URLを「ページ番号」にしておくこと。

これでGETで遷移せず、ajaxでページ遷移が可能となる。

 

■追記版のAjaxファイル

$.ajax({
  type: "POST", ←★POSTでもGETでもOK
  dataType: 'json',
  url: XXXXXX,
  data: {
   'page': page ←★表示させるページ番号
  },
}).done(function(res) {
 //ページングタグを受け取り描写
 var pagination_tag = window.atob(res.links);//base64エンコードしているのでデコードが必要

 $("#hoge").prepend(pagination_tag); ←★希望の場所にタグを追加
});

 

■jsファイル

後は簡単で、上のa.page-linkがクリックされると、data属性のページ番号を取得して、

先に作成したajaxを実行する。

$("#hoge").on('click', 'a.page-link', function(){
  var url = $(this).data('url');
  hoge(url);   ←★Ajaxを実行する関数に、ページ版番号を引き渡す
})

※a-.page-linkは動的に後から作成されるため、on('click', 'a.page-link', function) の形にしないとjqueryが動かない。

 

完成版 変更したければ、上記テンプレートでカスタマイズOK

f:id:aquashine:20200202134132p:plain

 

以上