Customizing pagination templates in Laravel 5.3

(This is part of a series of posts on New Features in Laravel 5.3.)

  1. Introducing Laravel Echo: An In-Depth Walk-Through
  2. The new $loop variable in Laravel 5.3
  3. Customizing additional parameters in FirstOrCreate in Laravel 5.3
  4. The new cache() global helper in Laravel 5.3
  5. New JSON-column where() and update() syntax in Laravel 5.3
  6. Advanced operations with Collection::where in Laravel 5.3
  7. Image dimension validation rules in Laravel 5.3
  8. Customizing pagination templates in Laravel 5.3
  9. 5.3 feature announcement notes from Laracon
  10. Routing changes in Laravel 5.3
  11. Introducing Laravel Scout
  12. Introducing Laravel Passport
  13. Introducing Mailables in Laravel 5.3
  14. Directory structure changes in Laravel 5.3
  15. The new Notification system in Laravel 5.3
  16. Update to queue workers in Laravel 5.3
  17. Using Vue in Laravel 5.3, with the Vue bootstrap and sample component
  18. Defining console commands via closure in Laravel 5.3

Laravel's pagination library is brilliant, because pagination is a common task that is a surprising amount of work to implement. In the past, if you wanted to customize your pagination templates, it was just as simple to customize your pagination template as it was to work with the rest of the pagination library.

However, for the sake of making the pagination library easier to extract for non-Laravel projects, Laravel 5.0 (or maybe even earlier?) introduced a much more complex—but more portable—system for pagination templates.

Thankfully, in Laravel 5.3, we're going to go back to how it always was: simple and easy.

How pagination works in Laravel #

If you're not familiar, here's a quick rundown of how it works to use pagination in Laravel.

// routes file
Route::get('tasks', function () {
    return view('tasks.index')
        ->with('tasks', Task::paginate(10));
});
// resource/views/tasks/index.blade.php
@foreach ($tasks as $task)
    <!-- echo the task or whatever -->
@endforeach

{{ $tasks->links() }}

By default, the paginate() method on your Eloquent objects reads the query parameters of your request and detects which page you're on. So in this example, it'll read the ?page query parameter and grab 10 records for that page. It'll pass those 10 in, and when we foreach on the $tasks variable, we'll just be looping over those 10.

But if you retrieve those 10 records using paginate() instead of something like all(), you get a new method available on your $tasks object (or other Eloquent result) named links(), and this method returns the view string appropriate for showing a list of pagination buttons:

<ul class="pagination">
    <li class="disabled"><span>&laquo;</span></li>

    <li class="active"><span>1</span></li>
    <li><a href="http://53pagination.dev?page=2">2</a></li>
    <li><a href="http://53pagination.dev?page=3">3</a></li>

    <li><a href="http://53pagination.dev?page=2" rel="next">&raquo;</a></li>
</ul>

Customizing the pagination template in Laravel 5.3 #

OK, so let's finally get to the dirt. How do you customize this template in 5.3?

By default, the template that is rendering this can be found in the Illuminate\Pagination component: resources/views/bootstrap-3.blade.php. This is what it looks like right now:

<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>

If you want to customize the pagination, you have two options: you can either publish the built-in view and edit it, or you can create a new file and manually link the Paginator to it.

Publishing the files #

Probably the easiest option is to run php artisan vendor:publish. It'll publish the template to vendor/pagination and you can just edit it there. This is the preferred option unless you have some specific customization needs.

Manually linking the files #

If you'd like to instead create your own pagination file and manually link to it, you can do that too. Create a new file that's a duplicate of that file, and modify it for your needs. Save it somewhere in resources/views; for now let's keep it simple and use resources/views/partials/pagination.blade.php.

Now, let's register it. Run \Illuminate\Pagination\LengthAwarePaginator::defaultView('partials.paginator') in the boot() method of a service provider.

Note: If you'd like to customize which template is used just by a single paginator, you can pass the view name to the links() method: {{ $users->links('partials.paginator') }}.

Overview #

So, to get this entire thing to work, I took these steps:

  1. Clone the latest version of Laravel 5.3
  2. Composer install
  3. php artisan vendor:publish
  4. Edit resources/views/vendor/pagination/default.blade.php and customize it to my heart's desire

That's it!

Note: These instructions show you how to customize the length-aware paginator, which is the most common. But if you're working with the simple paginator, you can customize that too. Just use the file named simple-default as your base instead of default.


Comments? I'm @stauffermatt on Twitter


Tags: laravel | laravel 5.3

Matt Stauffer headshot

Hi, I'm Matt Stauffer.

I'm partner & technical director at Tighten Co.

You can find me on Twitter at @stauffermatt


Like what you're reading?

I wrote an entire 450+ page book for O'Reilly: Laravel: Up and Running.

You can order the eBook or print book today.