Skip to content

Instantly share code, notes, and snippets.

@KaiCMueller
Created August 27, 2018 15:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KaiCMueller/6692ee84f51341acf582e2103f05f3d4 to your computer and use it in GitHub Desktop.
Save KaiCMueller/6692ee84f51341acf582e2103f05f3d4 to your computer and use it in GitHub Desktop.
Adding page numbers to EasyAdmin list views
{% trans_default_domain 'EasyAdminBundle' %}
{% set _paginator_request_parameters = _request_parameters|merge({'referer': null}) %}
{% if paginator.haveToPaginate %}
<div class="list-pagination">
<div class="row">
<div class="col-sm-3 hidden-xs list-pagination-counter">
{{ 'paginator.counter'|trans({ '%start%': paginator.currentPageOffsetStart, '%end%': paginator.currentPageOffsetEnd, '%results%': paginator.nbResults})|raw }}
</div>
<div class="col-xs-12 col-sm-9">
<ul class="pagination list-pagination-paginator {{ 1 == paginator.currentPage ? 'first-page' : '' }} {{ paginator.hasNextPage ? '' : 'last-page' }}">
{% if 1 == paginator.currentPage %}
<li class="disabled">
<span>
<i class="fa fa-angle-double-left"></i> {{ 'paginator.first'|trans }}
</span>
</li>
{% else %}
<li>
<a href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: 1 }) ) }}">
<i class="fa fa-angle-double-left"></i> {{ 'paginator.first'|trans }}
</a>
</li>
{% endif %}
{% if paginator.hasPreviousPage %}
<li>
<a href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: paginator.previousPage }) ) }}">
<i class="fa fa-angle-left"></i> {{ 'paginator.previous'|trans }}
</a>
</li>
{% else %}
<li class="disabled">
<span>
<i class="fa fa-angle-left"></i> {{ 'paginator.previous'|trans }}
</span>
</li>
{% endif %}
{# BEGIN DISPLAYING PAGE NUMBERS #}
{# the number of pages that are displayed around the active page #}
{% set nearbyPagesLimit = 5 %}
{% if paginator.currentPage > 1 %}
{% for i in range(paginator.currentPage-nearbyPagesLimit, paginator.currentPage-1) if ( i > 0 ) %}
<li>
<a href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: i }) ) }}">{{ i }}</a>
</li>
{% endfor %}
{% endif %}
<li>
<a class="current">{{ paginator.currentPage }}</a>
</li>
{% if paginator.currentPage < paginator.nbPages %}
{% for i in range(paginator.currentPage+1, paginator.currentPage + nearbyPagesLimit) if ( i <= paginator.nbPages ) %}
<li>
<a href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: i }) ) }}">{{ i }}</a>
</li>
{% endfor %}
{% endif %}
{# END DISPLAYING PAGE NUMBERS #}
{% if paginator.hasNextPage %}
<li>
<a href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: paginator.nextPage }) ) }}">
{{ 'paginator.next'|trans }} <i class="fa fa-angle-right"></i>
</a>
</li>
{% else %}
<li class="disabled">
<span>
{{ 'paginator.next'|trans }} <i class="fa fa-angle-right"></i>
</span>
</li>
{% endif %}
{% if paginator.currentPage < paginator.nbPages %}
<li>
<a href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: paginator.nbPages }) ) }}">
{{ 'paginator.last'|trans }} <i class="fa fa-angle-double-right"></i>
</a>
</li>
{% else %}
<li class="disabled">
<span>
{{ 'paginator.last'|trans }} <i class="fa fa-angle-double-right"></i>
</span>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
{% endif %}
@KaiCMueller
Copy link
Author

KaiCMueller commented Aug 27, 2018

screenshot 2018-08-27 17 17 01

This is the original EasyAdmin paginator template enhanced by page numbers. In between the "previous" and "next" buttons, the current page number is shown and a configurable amount of foregoing and following page numbers. Inspired by https://gist.github.com/SimonSimCity/4594748

To use this this custom template, copy it to your applications' template folder. For a Symfony 4 application, the correct location would be /templates/bundles/EasyAdminBundle/default/paginator.html.twig. Symfony will replace the template automatically.

@ardentsword
Copy link

ardentsword commented Mar 20, 2019

Great work! I used it for a while with great please. It's a real shame they denied your pull-request, I honestly think it would be a great addition.

Unfortunately, EasyCorp messed up the theme in EasyAdmin version 2, they now use some kind of stripped down version of bootstrap 3 made for select2 ( https://select2.github.io/select2-bootstrap-theme/ ). It doesn't contain a theme for the nav pagination from bootstrap meaning it completely breaks your implementation.
Pretty much the only useful element I found is the btn class. I made a quick implementation based on your work. It doesn't look the best but it's better than nothing:

{% trans_default_domain 'EasyAdminBundle' %}

{% set _paginator_request_parameters = _request_parameters|merge({'referer': null}) %}

<div class="list-pagination">
    <div class="list-pagination-counter">
        {{ 'paginator.results'|transchoice(paginator.nbResults)|raw }}
    </div>

    <div class="pager pagination list-pagination-paginator {{ not paginator.hasPreviousPage ? 'first-page' }} {{ not paginator.hasNextPage ? 'last-page' }}">
        <a class="btn btn-secondary {{ not paginator.hasPreviousPage ? 'disabled' }}"
           href="{{ not paginator.hasPreviousPage ? '#' : path('easyadmin', _paginator_request_parameters|merge({ page: paginator.previousPage }) ) }}">
            <i class="fa fa-angle-left"></i> <span class="btn-label">{{ 'paginator.previous'|trans }}</span>
        </a>

        {# BEGIN DISPLAYING PAGE NUMBERS #}

        {# the number of pages that are displayed around the active page #}
        {% set nearbyPagesLimit = 5 %}

        {% if paginator.currentPage > 1 %}
            {% for i in range(paginator.currentPage-nearbyPagesLimit, paginator.currentPage-1) if ( i > 0 ) %}
                <a class="btn btn-secondary" href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: i }) ) }}">{{ i }}</a>
            {% endfor %}
        {% endif %}

        <a class="btn btn-secondary" class="current" style="background-color: #e3e7ed">{{ paginator.currentPage }}</a>

        {% if paginator.currentPage < paginator.nbPages %}
            {% for i in range(paginator.currentPage+1, paginator.currentPage + nearbyPagesLimit) if ( i <= paginator.nbPages ) %}
                <a class="btn btn-secondary" href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: i }) ) }}">{{ i }}</a>
            {% endfor %}
        {% endif %}

        {# END DISPLAYING PAGE NUMBERS #}

        <a class="btn btn-secondary {{ not paginator.hasNextPage ? 'disabled' }}"
           href="{{ not paginator.hasNextPage ? '#' : path('easyadmin', _paginator_request_parameters|merge({ page: paginator.nextPage }) ) }}">
            <span class="btn-label">{{ 'paginator.next'|trans }}</span> <i class="fa fa-angle-right"></i>
        </a>
    </div>
</div>

@florianrusch
Copy link

@ardentsword You can still use the code from @KaiCMueller. You just have to add this css classes (Read here how you can add additional css assets):

.pagination {
    display: -ms-flexbox;
    display: flex;
    padding-left: 0;
    list-style: none;
    border-radius: 0.25rem;
}

.page-link {
    position: relative;
    display: block;
    padding: 0.5rem 0.75rem;
    margin-left: -1px;
    line-height: 1.25;
    color: #007bff;
    background-color: #fff;
    border: 1px solid #dee2e6;
}

.page-link:hover {
    z-index: 2;
    color: #0056b3;
    text-decoration: none;
    background-color: #e9ecef;
    border-color: #dee2e6;
}

.page-link:focus {
    z-index: 3;
    outline: 0;
    box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}

.page-item:first-child .page-link {
    margin-left: 0;
    border-top-left-radius: 0.25rem;
    border-bottom-left-radius: 0.25rem;
}

.page-item:last-child .page-link {
    border-top-right-radius: 0.25rem;
    border-bottom-right-radius: 0.25rem;
}

.page-item.active .page-link {
    z-index: 3;
    color: #fff;
    background-color: #007bff;
    border-color: #007bff;
}

.page-item.disabled .page-link {
    color: #6c757d;
    pointer-events: none;
    cursor: auto;
    background-color: #fff;
    border-color: #dee2e6;
}

.pagination-lg .page-link {
    padding: 0.75rem 1.5rem;
    font-size: 1.25rem;
    line-height: 1.5;
}

.pagination-lg .page-item:first-child .page-link {
    border-top-left-radius: 0.3rem;
    border-bottom-left-radius: 0.3rem;
}

.pagination-lg .page-item:last-child .page-link {
    border-top-right-radius: 0.3rem;
    border-bottom-right-radius: 0.3rem;
}

.pagination-sm .page-link {
    padding: 0.25rem 0.5rem;
    font-size: 0.875rem;
    line-height: 1.5;
}

.pagination-sm .page-item:first-child .page-link {
    border-top-left-radius: 0.2rem;
    border-bottom-left-radius: 0.2rem;
}

.pagination-sm .page-item:last-child .page-link {
    border-top-right-radius: 0.2rem;
    border-bottom-right-radius: 0.2rem;
}

@commonpike
Copy link

Updated @ardentsword version to include 'first' and 'last' buttons:

{% trans_default_domain 'EasyAdminBundle' %}

{% set _paginator_request_parameters = _request_parameters|merge({'referer': null}) %}

<div class="list-pagination">
    <div class="list-pagination-counter">
        {{ 'paginator.results'|transchoice(paginator.nbResults)|raw }}
    </div>

    <div class="pager pagination list-pagination-paginator {{ not paginator.hasPreviousPage ? 'first-page' }} {{ not paginator.hasNextPage ? 'last-page' }}">
        
        <a class="btn btn-secondary {{ 1 == paginator.currentPage ? 'disabled' }}"
            href="{{ 1 == paginator.currentPage ? '#' : path('easyadmin', _paginator_request_parameters|merge({ page: 1 }) ) }}">
            <i class="fa fa-angle-double-left"></i> <span class="btn-label">{{ 'paginator.first'|trans }}</span>
        </a>

        <a class="btn btn-secondary {{ not paginator.hasPreviousPage ? 'disabled' }}"
           href="{{ not paginator.hasPreviousPage ? '#' : path('easyadmin', _paginator_request_parameters|merge({ page: paginator.previousPage }) ) }}">
            <i class="fa fa-angle-left"></i> <span class="btn-label">{{ 'paginator.previous'|trans }}</span>
        </a>

        {# BEGIN DISPLAYING PAGE NUMBERS #}

        {# the number of pages that are displayed around the active page #}
        {% set nearbyPagesLimit = 5 %}

        {% if paginator.currentPage > 1 %}
            {% for i in range(paginator.currentPage-nearbyPagesLimit, paginator.currentPage-1) if ( i > 0 ) %}
                <a class="btn btn-secondary" href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: i }) ) }}">{{ i }}</a>
            {% endfor %}
        {% endif %}

        <a class="btn btn-secondary" class="current" style="background-color: #e3e7ed">{{ paginator.currentPage }}</a>

        {% if paginator.currentPage < paginator.nbPages %}
            {% for i in range(paginator.currentPage+1, paginator.currentPage + nearbyPagesLimit) if ( i <= paginator.nbPages ) %}
                <a class="btn btn-secondary" href="{{ path('easyadmin', _paginator_request_parameters|merge({ page: i }) ) }}">{{ i }}</a>
            {% endfor %}
        {% endif %}

        {# END DISPLAYING PAGE NUMBERS #}

        <a class="btn btn-secondary {{ not paginator.hasNextPage ? 'disabled' }}"
           href="{{ not paginator.hasNextPage ? '#' : path('easyadmin', _paginator_request_parameters|merge({ page: paginator.nextPage }) ) }}">
            <span class="btn-label">{{ 'paginator.next'|trans }}</span> <i class="fa fa-angle-right"></i>
        </a>

        <a class="btn btn-secondary {{ paginator.currentPage == paginator.nbPages ? 'disabled' }}"
            href="{{ paginator.currentPage == paginator.nbPages ? '#' : path('easyadmin', _paginator_request_parameters|merge({ page: paginator.nbPages }) ) }}">
            <i class="fa fa-angle-double-right"></i> <span class="btn-label">{{ 'paginator.last'|trans }}</span>
        </a>

    </div>
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment