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>&laquo;</span></li>
        @else
            <li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">&laquo;</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">&raquo;</a></li>
        @else
            <li class="disabled"><span>&raquo;</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('&hellip;');
    }
}

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") }}