jQueryとAjaxとLaravelでページネーションを実装する

# LaravelのページネーションをAjaxで実装する
LaravelのページネーションをAjaxで実装してみたので、メモしておきます。
参考:https://laravel.com/docs/5.8/pagination#displaying-pagination-results

なお、Laravelでは、`request()->view()`で簡単にviewを返すことができるので
それを利用しています。(トレンドは、jsonを返すのでしょうが。。。)
https://laravel.com/docs/5.8/responses#other-response-types

jsonを返す場合はこちらの記事を参考にするといいかもしれません。
https://qiita.com/zaburo/items/3104bde70b8eb70d3f09

---
- Laravel
- jQuery
- blade

---

## 実装の流れ
1. テンプレートを用意
2. ListController.phpとListApiConroller.phpを作成
3. `php artisan vendor:publish --tag=laravel-pagination`コマンド実行
4. ページネーション用のテンプレートを修正
5. AppServiceProviderに追加
6. Ajaxの処理を実装

### 1. テンプレートを用意

```html:index.blade.php
{{-- 検索フォーム --}}
<input type="text" name="id">
<input type="text" name="name">

<div id="list_wrap">
  @include('list')
</div>
```

```html:list.blade.php
{{-- なんかしらのリスト --}}
<table>
  <tbody>
    @foreach ($contents as $k = $v)
      <tr>
        <td class="id">{{$v->id}}</td>
        <td class="name">{{$v->name}}</td>
      </tr>
    @endforeach
  </tbody>
</table>

{{-- ページネーションリンク --}}
{{$contents->links()}}

```
ページネーションリンクにパラメータ付与する場合は以下のように記述する。
$paramはcontrollerから渡す
`{{$contents->appends($param)->links()}}`

### 2. ListController.phpとListApiConroller.phpを作成

```php:ListController.php
public function index()
{
    $contents = List::all();
    
    // ページネーションリンクのカスタマイズ
    $contents->withPath('api/page/');

    return view('index', compact(
        'contents'
    ));
}
```
```php:ListApiController.php

public function page(Request $request, List $list)
{
    // パラメータのセット
    $param['id'] = $request->id ?? '';
    $param['name'] = $request->name ?? '';

    // 検索
    $list = $list->where('id', $param['id']);
    $list = $list->where('name', $param['name']);

    // pagination
    $contents = $list->paginate(30);

    return response()->view(
        'list',
        compact('contents', 'param')
    );
}
```
withPath()メゾッドでpaginatioのリンクをカスタマイズできます。

### 3. コマンド実行
`php artisan vendor:publish --tag=laravel-pagination`を実行すると4のファイルが、
`resources/views/vendor/pagination`配下に作られます。

### 4. ページネーション用のテンプレートを修正
```html:bootstrap-4.blade.php
@if ($paginator->hasPages())
    <ul class="pagination">
        {{-- Previous Page Link --}}
        @if ($paginator->onFirstPage())
            <li class="page-item disabled button"><span class="page-link">&laquo;</span></li>
        @else
            <li class="page-item button"><button class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</button></li>
        @endif

        {{-- Pagination Elements --}}
        @foreach ($elements as $element)
            {{-- "Three Dots" Separator --}}
            @if (is_string($element))
                <li class="page-item disabled button"><span class="page-link">{{ $element }}</span></li>
            @endif

...省略
```

このファイルのaタグをbuttonタグに変更し、リンクを無効化します。(上記は変更済み)

### 5. AppServiceProviderに追加
```php:AppServiceProvider.php
use Illuminate\Pagination\Paginator;

public function boot()
{
    Paginator::defaultView('vendor/pagination/bootstrap-4');

    Paginator::defaultSimpleView('vendor/pagination/bootstrap-4');
}
```
上記の通り、AppServiceProvider.phpに登録します。
ファイル名を変更した方が良いと思います。
また、特定のページのみで利用する場合には、`Request::url()`を使って、条件分岐をするなどしました。

### 6. Ajax処理を実装
```javascript:paginate.js
// ページネーション
$('body').on('click', 'button.page-link', function () {
    let url = $(this).attr('href');
    $.get(url)
    .done(function (response) {
        $('#list_wrap').html('');
        $('#list_wrap').html(response);
    })
    .fail(function (e) {
        alert('データの取得に失敗しました。');
    })
})
```

ページネーションリンクの有効化/無効化はLaravel側が勝手にやってくれます。
検索の部分は省略。ページネーションや検索に合わせてURLを変更する場合は、
`jQuery.param()`でパラメタ作って`pushState()`を使って変更しました。