Livewireはコンポーネント内で結果をペジネーションする機能を提供します。この機能はLaravelのネイティブページネーション機能にフックしているため、目に見えない機能のように感じるはずです。
ペジネーションデータ
show-posts
コンポーネントがあり、結果を1ページあたり10件の投稿に制限したいとします。
Livewireが提供するWithPagination
トレイトを使用して、結果をページ分割できます。
use Livewire\WithPagination;
class ShowPosts extends Component
{
use WithPagination;
public function render()
{
return view('livewire.show-posts', [
'posts' => Post::paginate(10),
]);
}
}
<div>
@foreach ($posts as $post)
...
@endforeach
{{ $posts->links() }}
</div>
これで、投稿の下部にさまざまなページのHTMLリンクがレンダーリングされ、結果がページ付けされます。
データのフィルタリング後のペジネーションリセット
ペジネーションした結果セットをフィルタリングするときの一般的なパターンは、フィルタリングを適用したときに現在のページを"1"にリセットすることです。
たとえば、ユーザーがデータセットのページ"4"にアクセスし、検索フィールドに入力して結果を絞り込む場合、通常はページを"1"にリセットするのが望ましいでしょう。
LivewireのWithPagination
トレイトは、これを行うために->resetPage()
メソッドを用意しています。
このメソッドは、updating/updated
ライフサイクルフックと組み合わせて使用して、特定のコンポーネントデータが更新されたときにページをリセットできます。
use Livewire\WithPagination;
class ShowPosts extends Component
{
use WithPagination;
public $search = '';
public function updatingSearch()
{
$this->resetPage();
}
public function render()
{
return view('livewire.show-posts', [
'posts' => Post::where('title', 'like', '%'.$this->search.'%')->paginate(10),
]);
}
}
Multiple paginators on the same page
Because Livewire hardcodes the $page
property inside the
WithPagination
trait, there is no way to have two different
paginators on the same page because each will be competing for the same
property name in the query string of the URL bar.
Here's an example of two different components that might exist on the same page. By giving the second one (the comments one) a name, Livewire will pick it up and handle everything accordingly.
class ShowPosts extends Livewire\Component
{
public function render()
{
return view('livewire.show-posts', [
'posts' => Post::paginate(10),
]);
}
}
class ListPostComments extends Livewire\Component
{
public Post $post;
public function render()
{
return view('livewire.show-posts', [
'posts' => $post->comments()->paginate(10, ['*'], 'commentsPage'),
]);
}
}
Now in the query string, both paginators will be represented like so:
?page=2&commentsPage=3
Bootstrapページネーションテーマの使用
Laravelと同様に、Livewireのデフォルトのペジネーションビューはスタイル設定にTailwindクラスを使用します。アプリケーションでBootstrapを使用する場合は、コンポーネントの$paginationTheme
プロパティを使用して、ページネーションビューのBootstrapテーマを有効にできます。
class ShowPosts extends Component
{
use WithPagination;
protected $paginationTheme = 'bootstrap';
カスタムページネーションビューの使用
Livewireは、$results->links()
を呼び出すときにレンダーされる、ページネーションリンクのBladeビューをカスタマイズする方法を3つ提供しています。
方法A:ビュー名を->links()
メソッドへ直接渡します。
<div>
@foreach ($posts as $post)
...
@endforeach
{{ $posts->links('custom-pagination-links-view') }}
</div>
方法B:コンポーネントのpaginationView()
メソッドをオーバーライドします。
class ShowPosts extends Component
{
use WithPagination;
...
public function paginationView()
{
return 'custom-pagination-links-view';
}
...
}
方法C: LiveWireのペジネーションビューをリソース公開します。
Livewireのページネーションビューをresources/views/vendor/livewire
に公開するには、以下のArtisanコマンドを使用します。
php artisan livewire:publish --pagination
{note} 残念ながらLivewireは、
Paginator::defaultView()
を使用してサービスプロバイダー内で定義したカスタムビューを上書きします。
どのメソッドを使用する場合も、ペジネーションコンポーネントでアンカータグの代わりに、次のメソッドで
wire:click
ハンドラーを使用する必要があります。
nextPage
次のページに移動previousPage
前のページに移動gotoPage($page)
特定のページに移動
デフォルトのlivewireペジネタがどのように機能するかについては、以下の例を参考にしてください。
<div>
@if ($paginator->hasPages())
<nav role="navigation" aria-label="Pagination Navigation" class="flex justify-between">
<span>
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
{!! __('pagination.previous') !!}
</span>
@else
<button wire:click="previousPage" wire:loading.attr="disabled" rel="prev" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
{!! __('pagination.previous') !!}
</button>
@endif
</span>
<span>
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<button wire:click="nextPage" wire:loading.attr="disabled" rel="next" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
{!! __('pagination.next') !!}
</button>
@else
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
{!! __('pagination.next') !!}
</span>
@endif
</span>
</nav>
@endif
</div>