Last active
March 12, 2025 21:25
-
-
Save maxpou/612359ed4af4cc5c4f06 to your computer and use it in GitHub Desktop.
Example of pagination with Twig
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{# | |
Parameters: | |
* nbPages (int): number of pages | |
* currentPage (int): current pages | |
* url (string): route name & query (string): route parameter | |
ex: list/page-5?q=myFilter (5 = page and query = myFilter) | |
#} | |
{% spaceless %} | |
{% if nbPages > 1 %} | |
{# Number of page around current page+1 #} | |
{% set nearbyPagesLimit = 4 %} | |
<div> | |
<ul class="pagination"> | |
{% if currentPage != 1 %} | |
<li> | |
<a href="{{ path(url, { 'page': 1, 'q': query }) }}">First</a> | |
</li> | |
{% endif %} | |
{% for i in 1..nbPages %} | |
{% if 0 == (currentPage - nearbyPagesLimit) - loop.index %} {# dot before #} | |
<li class="disabled"><a href="#">...</a></li> | |
{% elseif 0 == (currentPage + nearbyPagesLimit) - loop.index %} {# dot after #} | |
<li class="disabled"><a href="#">...</a></li> | |
{% elseif 0 < (currentPage - nearbyPagesLimit) - loop.index %} {# hide all before #} | |
{% elseif 0 > (currentPage + nearbyPagesLimit) - loop.index %} {# hide all after #} | |
{% else %} | |
<li {% if currentPage == loop.index %} class="active"{% endif %}> | |
<a href="{{ path(url, { 'page': loop.index, 'q': query }) }}">{{ loop.index }}</a> | |
</li> | |
{% endif %} | |
{% endfor %} | |
{% if currentPage != nbPages %} | |
<li> | |
<a href="{{ path(url, { 'page': nbPages, 'q': query }) }}">Last</a> | |
</li> | |
{% endif %} | |
</ul> | |
</div> | |
{% endif %} | |
{% endspaceless %} |
Correct. Thanks a lot. I've updated the code.
{% macro pagination(total, current, pageQueryParam = 'page', nearbyPagesLimit = 4) %}
{% if total > 1 %}
<ul class="pagination my-4">
{% for i in 1..total %}
{% if 0 == (current - nearbyPagesLimit) - loop.index %}
<li class="page-item"><a href="{{ (app.request.pathInfo ~ '?' ~ (app.request.query.all|merge({(pageQueryParam): 1})|url_encode))|e }}" class="page-link">1</a></li>
{% if 1 != loop.index %}
<li class="page-item">
<a href="javascript:void(0)" class="page-link">...</a>
</li>
{% endif %}
{% elseif 0 == (current + nearbyPagesLimit) - loop.index and (current + nearbyPagesLimit) < total %}
<li class="page-item">
<a href="javascript:void(0)" class="page-link">...</a>
</li>
{% elseif 0 < (current - nearbyPagesLimit) - loop.index %}
{% elseif 0 > (current + nearbyPagesLimit) - loop.index %}
{% else %}
<li class="page-item{{ current == loop.index ? ' active' }}">
<a href="{{ (app.request.pathInfo ~ '?' ~ (app.request.query.all|merge({(pageQueryParam): loop.index})|url_encode))|e }}" class="page-link">{{ loop.index }}</a>
</li>
{% endif %}
{% endfor %}
{% if current != total and (current + nearbyPagesLimit) < total %}
<li class="page-item"><a href="{{ (app.request.pathInfo ~ '?' ~ (app.request.query.all|merge({(pageQueryParam): total})|url_encode))|e }}" class="page-link">{{ total }}</a></li>
{% endif %}
</ul>
{% endif %}
{% endmacro %}
I didn't like how the page had to be passed in with the macro so I decided to make it use the app.request
object to retain all query parameters and only modify the page
query parameter (with the option to change what the page query param is called). This assumes that pagination will always be hitting the same route the user is already on (which is true in my case but if not for your case you can easily modify the macro).
I also changed it to display via bootstrap 4.
thanks, for your share ;-)
Pagination with a variable.
<nav aria-label="Page navigation example">
<ul
class="pagination justify-content-center">
{# precedent #}
<li class="page-item {{ app.request.query.get('page')==1 or app.request.query.get('page')==0 ? 'disabled' }} ">
{% if app.request.query.get('page') is defined and app.request.query.get('page')>1 %}
{% set precedent = app.request.query.get('page') -1 %}
{% else %}
{% set precedent = 1 %}
{% endif %}
<a class="page-link" href="{{ path('¤entity¤_index',{'page':precedent,'tri':app.request.query.get('tri'),'ordre':app.request.query.get('ordre')}) }}">
<span aria-hidden="true">«</span>
</a>
</li>
{% if pagesMaxi/10>6 %}
{# 1 #}
<li class="page-item">
<a class="page-link" href="{{ path('¤entity¤_index',{'page':1,'tri':app.request.query.get('tri'),'ordre':app.request.query.get('ordre')}) }}">1</a>
</li>
{# pages millieu #}
{% for item in 1..5 %}
<li class="page-item">
<a class="page-link " href="{{ path('¤entity¤_index',{'page':(pagesMaxi/10/6*loop.index)|number_format(0),'tri':app.request.query.get('tri'),'ordre':app.request.query.get('ordre')}) }}">{{(pagesMaxi/10/6*loop.index)|number_format(0)}}</a>
</li>
{% endfor %}
{# maxi #}
<li class="page-item">
<a class="page-link" href={{ path('¤entity¤_index',{'page':(pagesMaxi/10)|number_format(0),'tri':app.request.query.get('tri'),'ordre':app.request.query.get('ordre')} ) }}>{{(pagesMaxi/10)|number_format(0)}}</a>
</li>
{% else %}
{% for item in 1..(pagesMaxi/10)|number_format(0) %}
<li class="page-item">
<a class="page-link " href="{{ path('¤entity¤_index',{'page':loop.index,'tri':app.request.query.get('tri'),'ordre':app.request.query.get('ordre')}) }}">{{loop.index}}</a>
</li>
{% endfor %}
{% endif %}
{# suivant #}
<li class="page-item {{ app.request.query.get('page') >= (pagesMaxi/10)|number_format ? 'disabled' }}">
{% if app.request.query.get('page')==0 %}
{% set suivant = 2 %}
{% else %}
{% set suivant = app.request.query.get('page') +1 %}
{% endif %}
<a class="page-link" href="{{ path('¤entity¤_index',{'page':suivant,'tri':app.request.query.get('tri'),'ordre':app.request.query.get('ordre')}) }}">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Qrzysio you're missing a
</nav>