【Laravel10 + Inertia + Vue3】Paginationを実装する(3)

Laravel

前回の記事の続きです。

この記事のゴール

前回は出力調整をしました。

今回は表示条件の変更とパラメータの受け渡しを行います。

  • メールアドレスのドメイン絞り込み
  • 1ページ当たりの表示件数変更
  • 並び順の変更

Inertiaの機能を使った形で実装を進めていきます。

これからやること

  • コントローラー編集
  • Inertiaテンプレート編集
  • ブラウザ確認

コントローラー編集

「app/Http/Controllers/UsersController.php」を編集・保存します。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\User;

class UsersController extends Controller
{
    public function index(Request $request)
    {
        $currentPage = $request->query('page') ?? 1;
        $perPage = $request->query('perPage') ?? 10;
        $domain = $request->query('domain') ?? '';
        $orderbyID = strcmp($request->query('orderbyID'), 'desc') === 0
                   ? 'desc'
                   : 'asc';
        $empty = User::selectRaw("''");
        return Inertia::render('UsersList', [
            'usersList' => User::where('email', 'LIKE', '%' . $domain)
                           ->orderby('id', $orderbyID)
                           ->paginate($perPage)
                           ->onEachSide(1)
                           ->withQueryString(),
            'domains' => User::selectRaw(
                            "substr(email, instr(email, '@'), length(email))
                            as domain"
                         )
                         ->union($empty)
                         ->distinct()
                         ->orderby('domain', 'asc')
                         ->get(),
            'perPages' => [ 5, 10, 20, 50, ],
            'currentPage' => $currentPage,
            'selectedDomain' => $domain,
            'selectedPerPage' => $perPage,
            'selectedOrderbyID' => $orderbyID,
        ]);
    }
}

URLパラメータから取得した値をそれぞれの変数に格納しています。

  • $currentPage: 現在のページ
  • $domain: 絞り込みドメイン名
  • $perPage: 表示件数
  • $orderbyID: 並び順

Inertiaテンプレート変数としてそれぞれ返しています。

  • usersList: ユーザー一覧
  • domains: ドメイン名一覧
  • perPages: 表示件数一覧
  • currentPage: 現在のページ
  • selectedDomain: 選択されたドメイン名
  • selectedPerPage: 選択された表示件数
  • selectedOrderbyID: 選択された並び順

Inertiaテンプレート編集

「resources/js/Pages/UsersList.vue」を編集・保存します。

<template>
  <layout title="Users">
    <div class="container mt-5">
      <div class="view-conditions mx-2">
        ドメイン:
        <select
          v-model="domain"
          class="py-0 bg-sky-200"
          @change="changeDomain"
        >
          <option v-for="d in domains" :value="d.domain">{{ d.domain.length > 0 ? d.domain : '指定しない' }}</option>
        </select>
        表示:
        <select
          v-model="perPage"
          class="py-0 bg-sky-200"
          @change="changePerPage"
        >
          <option v-for="p in perPages" :value="p">{{ p }}</option>
        </select>件
        並び順:ID
        <select
          v-model="orderbyID"
          class="py-0 bg-sky-200"
          @change="changeOrderbyID"
        >
          <option v-for="o in orderbyIDs" :value="o">{{ orderbyIDTexts[o] }}</option>
        </select>
      </div>
      <Pagination
        class="mt-6"
        :links="usersList.links"
        previousLabel="<img src='/img/previous.png' width='16' height='16' alt='Previous' title='Prev'>"
        nextLabel="<img src='/img/next.png' width='16' height='16' alt='Next' title='Next'>"
      />
      <ul>
        <li
          v-for="item in usersList.data"
          :key="item.id"
          class="p-2 hover:bg-green-200 rounded-lg"
        >
          {{ item.id }}: {{ item.name }} &lt;{{ item.email }}&gt;
        </li>
      </ul>
    </div>
  </layout>
</template>
    
<script>
import Pagination from '@/Components/Pagination.vue'
import { router } from '@inertiajs/vue3'

export default {
  components: {
    Pagination
  },
  props: {
    usersList: Object,
    domains: Object,
    perPages: Array,
    currentPage: {
      type: Number,
      default: 1,
    },
    selectedDomain: {
      type: String,
      default: '',
    },
    selectedPerPage: {
      type: Number,
      default: 10,
    },
    selectedOrderbyID: {
      type: String,
      default: 'asc',
    },
  },
  data () {
    return {
      domain: '',
      perPage: 10,
      orderbyID: 'asc',
      orderbyIDs: [ 'asc', 'desc' ],
      orderbyIDTexts: { asc: '昇順', desc: '降順' },
    };
  },
  methods: {
    getReloadUrl () {
      return '/users?page=' + this.currentPage
             + '&domain=' + this.domain
             + '&perPage=' + this.perPage
             + '&orderbyID=' + this.orderbyID
    },
    changeDomain () {
      router.visit(this.getReloadUrl());
    },
    changePerPage () {
      router.visit(this.getReloadUrl());
    },
    changeOrderbyID() {
      router.visit(this.getReloadUrl());
    },
  },
  mounted () {
    this.domain = this.selectedDomain;
    this.perPage = this.selectedPerPage;
    this.orderbyID = this.selectedOrderbyID;
  }
}
</script>

表示条件の変更時にそれぞれ表示変更用のメソッドを呼び出し、

router.visit() を実行して表示切替をしています。

Inertiaの公式ドキュメントはかなり頑張って色々と説明していますが、

これを読んだだけでは使い方がよくわからないと思います。

GitHub

実際にコードを書いて試行錯誤しながらでないと使い方が判らないと思います。

ブラウザ確認

WEBブラウザを再読み込みします。

ドメイン、表示件数、並び順のプルダウンが表示されました。

ページネーションのリンクをクリックしてページの切替もできています。

ドメインの絞り込みをしてみます。

ドメインのプルダウンが選択されたままの状態で表示が切り替わりました。

URLを確認してみます。

http://127.0.0.1:8000/users?page=6&domain=@example.com&perPage=10&orderbyID=asc

このようになっています。

表示件数を変更してみます。

選択したプルダウンが維持された状態で表示が切り替わりました。

URLを確認してみます。

http://127.0.0.1:8000/users?page=6&domain=@example.com&perPage=5&orderbyID=asc

このようになっています。

並び順を変えてみます。

並び順の選択が維持された状態で表示が降順に切り替わりました。

URLを確認してみます。

http://127.0.0.1:8000/users?page=6&domain=@example.com&perPage=5&orderbyID=desc

このようになっています。

ページの切替も問題なくできています。

今回はここまでです。お疲れさまでした。

コメント

タイトルとURLをコピーしました