Pagination
- Paginating Data
- Resetting Pagination After Filtering Data
- Multiple paginators on the same page
- Using The Bootstrap Pagination Theme
- Using A Custom Pagination View
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 @endforeach5 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.
An optional page name parameter may be passed through, if the pagination name is set to anything other than page
.
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 use WithPagination; 4 5 public function render() 6 { 7 return view('livewire.show-posts', [ 8 'posts' => Post::paginate(10), 9 ]);10 }11}
1class ListPostComments extends Livewire\Component 2{ 3 use WithPagination; 4 5 public Post $post; 6 7 public function render() 8 { 9 return view('livewire.show-posts', [10 'posts' => $post->comments()->paginate(10, ['*'], 'commentsPage'),11 ]);12 }13}
Now in the query string, both paginators will be represented like so:
1?page=2&commentsPage=3
To reset a specific paginator, you may pass through your custom page name using the ->resetPage()
method as found in the WithPagination
trait.
1class ListPostComments extends Livewire\Component 2{ 3 use WithPagination; 4 5 public $search = ''; 6 7 public function updatingSearch() 8 { 9 $this->resetPage('commentsPage');10 }11 12 public function render()13 {14 return view('livewire.show-posts', [15 'posts' => $post->comments()->where('title', 'like', '%'.$this->search.'%')->paginate(10, ['*'], 'commentsPage'),16 ]);17 }18}
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 Component2{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 @endforeach5 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
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 pagepreviousPage
to navigate to the previous pagegotoPage($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 @else11 <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 @endif15 </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 @else24 <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 @endif28 </span>29 </nav>30 @endif31</div>