Custom pagination view in Laravel 5
Laravel 4.2 has the option to specify a custom view in app/config/view.php
such as:
/*
|--------------------------------------------------------------------------
| Pagination View
|--------------------------------------------------------------------------
|
| This view will be used to render the pagination link output, and can
| be easily customized here to show any view you like. A clean view
| compatible with Twitter's Bootstrap is given to you by default.
|
*/
'pagination' => 'pagination_slider-alt'
This is gone in Laravel 5 at least regarding view.php
.
Is there a way to replicate this behavior in Laravel 5?
Solution 1:
In Laravel 5.3+ use
$users->links('view.name')
In Laravel 5.0 - 5.2 instead of
$users->render()
use
@include('pagination.default', ['paginator' => $users])
views/pagination/default.blade.php
@if ($paginator->lastPage() > 1)
<ul class="pagination">
<li class="{{ ($paginator->currentPage() == 1) ? ' disabled' : '' }}">
<a href="{{ $paginator->url(1) }}">Previous</a>
</li>
@for ($i = 1; $i <= $paginator->lastPage(); $i++)
<li class="{{ ($paginator->currentPage() == $i) ? ' active' : '' }}">
<a href="{{ $paginator->url($i) }}">{{ $i }}</a>
</li>
@endfor
<li class="{{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : '' }}">
<a href="{{ $paginator->url($paginator->currentPage()+1) }}" >Next</a>
</li>
</ul>
@endif
That's it.
If you have a lot of pages, use this template:
views/pagination/limit_links.blade.php
<?php
// config
$link_limit = 7; // maximum number of links (a little bit inaccurate, but will be ok for now)
?>
@if ($paginator->lastPage() > 1)
<ul class="pagination">
<li class="{{ ($paginator->currentPage() == 1) ? ' disabled' : '' }}">
<a href="{{ $paginator->url(1) }}">First</a>
</li>
@for ($i = 1; $i <= $paginator->lastPage(); $i++)
<?php
$half_total_links = floor($link_limit / 2);
$from = $paginator->currentPage() - $half_total_links;
$to = $paginator->currentPage() + $half_total_links;
if ($paginator->currentPage() < $half_total_links) {
$to += $half_total_links - $paginator->currentPage();
}
if ($paginator->lastPage() - $paginator->currentPage() < $half_total_links) {
$from -= $half_total_links - ($paginator->lastPage() - $paginator->currentPage()) - 1;
}
?>
@if ($from < $i && $i < $to)
<li class="{{ ($paginator->currentPage() == $i) ? ' active' : '' }}">
<a href="{{ $paginator->url($i) }}">{{ $i }}</a>
</li>
@endif
@endfor
<li class="{{ ($paginator->currentPage() == $paginator->lastPage()) ? ' disabled' : '' }}">
<a href="{{ $paginator->url($paginator->lastPage()) }}">Last</a>
</li>
</ul>
@endif
Solution 2:
For Laravel 5.3 (and may be in other 5.X versions) put custom pagination code in you view folder.
resources/views/pagination/default.blade.php
@if ($paginator->hasPages())
<ul class="pagination">
{{-- Previous Page Link --}}
@if ($paginator->onFirstPage())
<li class="disabled"><span>«</span></li>
@else
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">«</a></li>
@endif
{{-- Pagination Elements --}}
@foreach ($elements as $element)
{{-- "Three Dots" Separator --}}
@if (is_string($element))
<li class="disabled"><span>{{ $element }}</span></li>
@endif
{{-- Array Of Links --}}
@if (is_array($element))
@foreach ($element as $page => $url)
@if ($page == $paginator->currentPage())
<li class="active"><span>{{ $page }}</span></li>
@else
<li><a href="{{ $url }}">{{ $page }}</a></li>
@endif
@endforeach
@endif
@endforeach
{{-- Next Page Link --}}
@if ($paginator->hasMorePages())
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">»</a></li>
@else
<li class="disabled"><span>»</span></li>
@endif
</ul>
@endif
then call this pagination view file from the main view file as
{{ $posts->links('pagination.default') }}
Update the pagination/default.blade.php however you want
It works in 8.x versions as well.
Solution 3:
In Laravel 5 custom pagination is based on presenters (classes) instead of views.
Assuming in your routed code you have
$users = Users::paginate(15);
In L4 you used to do something like this in your views:
$users->appends(['sort' => 'votes'])->links();
In L5 you do instead:
$users->appends(['sort' => 'votes'])->render();
The render()
method accepts an Illuminate\Contracts\Pagination\Presenter
instance. You can create a custom class that implements that contract and pass it to the render()
method. Note that Presenter
is an interface, not a class, therefore you must implement it, not extend it. That's why you are getting the error.
Alternatively you can extend the Laravel paginator (in order to use its pagination logic) and then pass the existing pagination instance ($users->...
) to you extended class constructor. This is indeed what I did for creating my custom Zurb Foundation presenter based on the Bootstrap presenter provided by Laravel. It uses all the Laravel pagination logic and only overrides the rendering methods.
With my custom presenter my views look like this:
with(new \Stolz\Laravel\Pagination($users->appends(['sort' => 'votes'])))->render();
And my customized pagination presenter is:
<?php namespace Stolz\Laravel;
use Illuminate\Pagination\BootstrapThreePresenter;
class Pagination extends BootstrapThreePresenter
{
/**
* Convert the URL window into Zurb Foundation HTML.
*
* @return string
*/
public function render()
{
if( ! $this->hasPages())
return '';
return sprintf(
'<ul class="pagination" aria-label="Pagination">%s %s %s</ul></div>',
$this->getPreviousButton(),
$this->getLinks(),
$this->getNextButton()
);
}
/**
* Get HTML wrapper for disabled text.
*
* @param string $text
* @return string
*/
protected function getDisabledTextWrapper($text)
{
return '<li class="unavailable" aria-disabled="true"><a href="javascript:void(0)">'.$text.'</a></li>';
}
/**
* Get HTML wrapper for active text.
*
* @param string $text
* @return string
*/
protected function getActivePageWrapper($text)
{
return '<li class="current"><a href="javascript:void(0)">'.$text.'</a></li>';
}
/**
* Get a pagination "dot" element.
*
* @return string
*/
protected function getDots()
{
return $this->getDisabledTextWrapper('…');
}
}
Solution 4:
Whereas in Laravel 4.2 I would use:
{{ $users->links('view.name') }}
In Laravel 5 you can replicate the above with the following:
@include('view.name', ['object' => $users])
Now in the included view, $object
will have the pagination methods available, such as currentPage()
, lastPage()
, perPage()
, etc.
You can view all methods available at http://laravel.com/docs/5.0/pagination
Solution 5:
In 5.5
links()
is replaced with render()
which appears to work similarly. [Official DOC]
replace
{{ $replies->links() }}
with
{{ $replies->render("pagination::default") }}
Following commands will generate Pagination template in resources/views/vendor/pagination
artisan vendor:publish --tag=laravel-pagination
artisan vendor:publish
In any view file (blade files) you can use those template like following ex:
{{ $replies->render("pagination::default") }}
{{ $replies->render("pagination::bootstrap-4") }}
-
{{ $replies->render("pagination::simple-bootstrap-4") }}
{{ $replies->render("pagination::semantic-ui") }}