Pagination

Livewire offers the ability to paginate results within a component. This feature hooks into Laravel's native pagination features, so it should feel like an invisible feature to you.

Paginating Data

Let's say you have a show-posts component, but you want to limit the results to 10 posts per page.

You can paginate the results by using the WithPagination trait provided by Livewire.

            
1use Livewire\WithPagination;
2 
3class ShowPosts extends Component
4{
5 use WithPagination;
6 
7 public function render()
8 {
9 return view('livewire.show-posts', [
10 'posts' => Post::paginate(10),
11 ]);
12 }
13}
            
1<div>
2 @foreach ($posts as $post)
3 ...
4 @endforeach
5 
6 {{ $posts->links() }}
7</div>

Now there will be rendered HTML links for the different pages at the bottom of your posts, and the results will be paginated.

Resetting Pagination After Filtering Data

A common pattern when filtering a paginated result set is to reset the current page to "1" when filtering is applied.

For example, if a user visits page "4" of your data set, then types into a search field to narrow the results, it is usually desireable to reset the page to "1".

Livewire's WithPagination trait exposes a ->resetPage() method to accomplish this.

This method can be used in combination with the updating/updated lifecycle hooks to reset the page when certain component data is updated.

        
1use Livewire\WithPagination;
2 
3class ShowPosts extends Component
4{
5 use WithPagination;
6 
7 public $search = '';
8 
9 public function updatingSearch()
10 {
11 $this->resetPage();
12 }
13 
14 public function render()
15 {
16 return view('livewire.show-posts', [
17 'posts' => Post::where('title', 'like', '%'.$this->search.'%')->paginate(10),
18 ]);
19 }
20}

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.

        
1class ShowPosts extends Livewire\Component
2{
3 public function render()
4 {
5 return view('livewire.show-posts', [
6 'posts' => Post::paginate(10),
7 ]);
8 }
9}
        
1class ListPostComments extends Livewire\Component
2{
3 public Post $post;
4 
5 public function render()
6 {
7 return view('livewire.show-posts', [
8 'posts' => $post->comments()->paginate(10, ['*'], 'commentsPage'),
9 ]);
10 }
11}

Now in the query string, both paginators will be represented like so:

        
1?page=2&commentsPage=3

Using The Bootstrap Pagination Theme

Like Laravel, Livewire's default pagination view uses Tailwind classes for styling. If you use Bootstrap in your application, you can enable the Bootstrap theme for the pagination view using the $paginationTheme property on your component.

        
1class ShowPosts extends Component
2{
3 use WithPagination;
4 
5 protected $paginationTheme = 'bootstrap';

Using A Custom Pagination View

Livewire provides 3 ways to customize the pagination links Blade view, rendered when calling $results->links().

Method A: Pass view name directly to the ->links() method.

        
1<div>
2 @foreach ($posts as $post)
3 ...
4 @endforeach
5 
6 {{ $posts->links('custom-pagination-links-view') }}
7</div>

Method B: Override the paginationView() method in your component.

        
1class ShowPosts extends Component
2{
3 use WithPagination;
4 
5 ...
6 
7 public function paginationView()
8 {
9 return 'custom-pagination-links-view';
10 }
11 
12 ...
13}

Method C: Publish the Livewire pagination views.

You can publish the Livewire pagination views to resources/views/vendor/livewire using the following artisan command:

        
1php artisan livewire:publish --pagination
Unfortunately, Livewire will overwrite a custom view you have defined inside a service provider using: Paginator::defaultView().

When using either method, instead of anchor tags in your pagination component, you should use wire:click handlers with the following methods:

  • nextPage to navigate to the next page
  • previousPage to navigate to the previous page
  • gotoPage($page) to navigate to a specific page.

See below for an example of how the default livewire paginator works.

        
1<div>
2 @if ($paginator->hasPages())
3 <nav role="navigation" aria-label="Pagination Navigation" class="flex justify-between">
4 <span>
5 {{-- Previous Page Link --}}
6 @if ($paginator->onFirstPage())
7 <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">
8 {!! __('pagination.previous') !!}
9 </span>
10 @else
11 <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">
12 {!! __('pagination.previous') !!}
13 </button>
14 @endif
15 </span>
16 
17 <span>
18 {{-- Next Page Link --}}
19 @if ($paginator->hasMorePages())
20 <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">
21 {!! __('pagination.next') !!}
22 </button>
23 @else
24 <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">
25 {!! __('pagination.next') !!}
26 </span>
27 @endif
28 </span>
29 </nav>
30 @endif
31</div>
← Previous Topic

Authorization

Next Topic →

Redirecting