{# | |
Source: http://dev.dbl-a.com/symfony-2-0/symfony2-and-twig-pagination/ | |
Updated by: Simon Schick <simonsimcity@gmail.com> | |
Parameters: | |
* currentFilters (array) : associative array that contains the current route-arguments | |
* currentPage (int) : the current page you are in | |
* paginationPath (string) : the route name to use for links | |
* showAlwaysFirstAndLast (bool) : Always show first and last link (just disabled) | |
* lastPage (int) : represents the total number of existing pages | |
#} | |
{% spaceless %} | |
{% if lastPage > 1 %} | |
{# the number of first and last pages to be displayed #} | |
{% set extremePagesLimit = 3 %} | |
{# the number of pages that are displayed around the active page #} | |
{% set nearbyPagesLimit = 2 %} | |
<div class="pagination"> | |
{% if currentPage > 1 %} | |
<a href="{{ path(paginationPath, currentFilters|merge({page: currentPage-1})) }}">Previous</a> | |
{% for i in range(1, extremePagesLimit) if ( i < currentPage - nearbyPagesLimit ) %} | |
<a href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a> | |
{% endfor %} | |
{% if extremePagesLimit + 1 < currentPage - nearbyPagesLimit %} | |
<span class="sep-dots">...</span> | |
{% endif %} | |
{% for i in range(currentPage-nearbyPagesLimit, currentPage-1) if ( i > 0 ) %} | |
<a href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a> | |
{% endfor %} | |
{% elseif showAlwaysFirstAndLast %} | |
<span class="disabled">Previous</span> | |
{% endif %} | |
<a href="{{ path(paginationPath, currentFilters|merge({ page: currentPage })) }}" | |
class="active">{{ currentPage }}</a> | |
{% if currentPage < lastPage %} | |
{% for i in range(currentPage+1, currentPage + nearbyPagesLimit) if ( i <= lastPage ) %} | |
<a href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a> | |
{% endfor %} | |
{% if (lastPage - extremePagesLimit) > (currentPage + nearbyPagesLimit) %} | |
<span class="sep-dots">...</span> | |
{% endif %} | |
{% for i in range(lastPage - extremePagesLimit+1, lastPage) if ( i > currentPage + nearbyPagesLimit ) %} | |
<a href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a> | |
{% endfor %} | |
<a href="{{ path(paginationPath, currentFilters|merge({page: currentPage+1})) }}">Next</a> | |
{% elseif showAlwaysFirstAndLast %} | |
<span class="disabled">Next</span> | |
{% endif %} | |
</div> | |
{% endif %} | |
{% endspaceless %} |
@SimonSimCity Thank you so much for making this, you are my hero.
Thank you for this gist and all other versions of this gist.
Another slight improvement for the issue I ran into today, when currentFilters is not defined, get the current route params:
{% if currentFilters is not defined %}{% set currentFilters = app.request.attributes.get('_route_params') %}{% endif %}
Thank you!
Thank you!
Might add aria-current="page"
to the active pagination link for better accessibility.
I just updated it for my next work project using UIkit.
I added scope
object and used all options from it.
Also I added two methods of URL building:
- page number in URL query parameters like
/news?page=4
- page number directly after
paginationPath
option like/news/4
I replaced path()
function with macros with |url_encode
filter to convert an object to URL query string.
Here's a fork: https://gist.github.com/Grawl/5ebe19aa808e9b4371938a697b1597e8
Will be good to add an option to modify page
URL query key to get /news?p=4
or /news?pagination=4
Thank you for the great work! I adapted your approach to build a paginator for the Symfony EasyAdmin bundle: https://gist.github.com/KaiCMueller/6692ee84f51341acf582e2103f05f3d4
As a warning to newer users Twig is deprecating the if appended to the end of the for statements
Twig 2.10 deprecated the inline if statements in for loops. You now have to use filters instead or move the if inside of the loop:
I wish there could be an update for this without the depreciated for statements.
@ulab @AliAkinK I actually fixed this problem years ago but never thought about uploading it here, if anyone is still interested:
I'm actually still actively using it, and it works quite well :)
{#
Source: http://dev.dbl-a.com/symfony-2-0/symfony2-and-twig-pagination/
Updated by: Simon Schick <simonsimcity@gmail.com>
Parameters:
* currentFilters (array) : associative array that contains the current route-arguments
* currentPage (int) : the current page you are in
* paginationPath (string) : the route name to use for links
* showAlwaysFirstAndLast (bool) : Always show first and last link (just disabled)
* lastPage (int) : represents the total number of existing pages
#}
{% apply spaceless %}
{% if lastPage > 1 %}
{# the number of first and last pages to be displayed #}
{% set extremePagesLimit = 3 %}
{# the number of pages that are displayed around the active page #}
{% set nearbyPagesLimit = 2 %}
{% if currentFilters is not defined %}{% set currentFilters = app.request.attributes.get('_route_params')|merge(app.request.query.all) %}{% endif %}
{% if paginationPath is not defined %}{% set paginationPath = app.request.attributes.get('_route') %}{% endif %}
{% if showAlwaysFirstAndLast is not defined %}{% set showAlwaysFirstAndLast = true %}{% endif %}
<nav aria-label="Page navigation">
<ul class="pagination">
{% if currentPage > 1 %}
<li class="page-item"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({page: currentPage-1})) }}">Previous</a></li>
{% for i in range(1, extremePagesLimit) | filter(i => i < currentPage - nearbyPagesLimit ) %}
<li class="page-item"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
{% if extremePagesLimit + 1 < currentPage - nearbyPagesLimit %}
<span class="sep-dots">...</span>
{% endif %}
{% for i in range(currentPage-nearbyPagesLimit, currentPage-1) | filter(i => i > 0 ) %}
<li class="page-item"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
{% elseif showAlwaysFirstAndLast %}
<li class="page-item disabled"><a class="page-link" href="#">Previous</a></li>
{% endif %}
<li class="page-item active"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({ page: currentPage })) }}">{{ currentPage }}</a></li>
{% if currentPage < lastPage %}
{% for i in range(currentPage+1, currentPage + nearbyPagesLimit) | filter(i => i <= lastPage) %}
<li class="page-item"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
{% if (lastPage - extremePagesLimit) > (currentPage + nearbyPagesLimit) %}
<span class="sep-dots">...</span>
{% endif %}
{% for i in range(lastPage - extremePagesLimit+1, lastPage) | filter( i => i > currentPage + nearbyPagesLimit ) %}
<li class="page-item"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({page: i})) }}">{{ i }}</a></li>
{% endfor %}
<li class="page-item"><a class="page-link" href="{{ path(paginationPath, currentFilters|merge({page: currentPage+1})) }}">Next</a></li>
{% elseif showAlwaysFirstAndLast %}
<li class="page-item disabled"><a class="page-link" href="#">Next</a></li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endapply %}
@ardentsword you have a typo with currentFilers vs currentFilters which always empties the current filters.