When creating a record listing page with filters using Laravel and Blade with Bootstrap 4, we encounter the following situation:
The pagination works perfectly, but after applying a filter and changing the page, the previously applied filter is lost. This occurs because Laravel's pagination already includes page links in the query parameters on the front-end, overriding the filters that are currently in the same location.
I created the method below that modifies the URL generated by Laravel Paginator to include the applied filters in the query parameters, preserving the page number.
function parseUrl(string $url): string
{
$queryString = request()->has('page') ? http_build_query(request()->except('page')) : request()->getQueryString();
if (!empty($queryString)) {
return $url . "&" . $queryString;
}
return $url;
}
Now just implement the method above in the view generated by Laravel when we execute the command:
php artisan vendor:publish --tag=laravel-pagination
A complete example of view bootstrap-4.blade.php:
@if ($paginator->hasPages())
@php
/**
* Modifica a url da paginação para incluir o filtro aplicado, preservando o numero da página.
* @param string $url
* @return string
*/
function parseUrl(string $url): string
{
$queryString = request()->has('page') ? http_build_query(request()->except('page')) : request()->getQueryString();
if (!empty($queryString)) {
return $url . "&" . $queryString;
}
return $url;
}
@endphp
<nav>
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
<span class="page-link" aria-hidden="true">‹</span>
</li>
@else
<li class="page-item">
<a class="page-link" href="{{ parseUrl($paginator->previousPageUrl()) }}" rel="prev" aria-label="@lang('pagination.previous')">‹</a>
</li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
@else
<li class="page-item"><a class="page-link" href="{{ parseUrl($url) }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li class="page-item">
<a class="page-link" href="{{ parseUrl($paginator->nextPageUrl()) }}" rel="next" aria-label="@lang('pagination.next')">›</a>
</li>
@else
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
<span class="page-link" aria-hidden="true">›</span>
</li>
@endif
</ul>
</nav>
@endif
This was my solution to this problem. Any suggestions, leave a comment below ;)