{# | |
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 %} |
radiocity
commented
May 21, 2019
There is a little bug showing the first dots, where it does this strange behavour:
And this would be the fixed sample, note there is no ...
separation between 1 and 2:
Also, this macro is adapted directly to render Bootstrap 3 lists.
{% macro pagination(total, current, url, nearbyPagesLimit = 4) %}
{% spaceless %}
{% if total > 1 %}
<ul class="pagination">
{% for i in 1..total %}
{% if 0 == (current - nearbyPagesLimit) - loop.index %}
<li><a href="{{ (url ~ 1)|e }}">1</a></li>
{% if 1 != loop.index %}
<li><span>…</span></li>
{% endif %}
{% elseif 0 == (current + nearbyPagesLimit) - loop.index and (current + nearbyPagesLimit) < total %}
<li><span>…</span></li>
{% elseif 0 < (current - nearbyPagesLimit) - loop.index %}
{% elseif 0 > (current + nearbyPagesLimit) - loop.index %}
{% else %}
<li {{ current == loop.index ? 'class="active"' }}>
{% if current == loop.index %}
<span>{{ loop.index }}</span>
{% else %}
<a href="{{ url ~ loop.index }}">{{ loop.index }}</a>
{% endif %}
</li>
{% endif %}
{% endfor %}
{% if current != total and (current + nearbyPagesLimit) < total %}
<li><a href="{{ (url ~ total)|e }}">{{ total }}</a></li>
{% endif %}
</ul>
{% endif %}
{% endspaceless %}
{% endmacro %}
Added prev
and next
buttons. Compatible with Twig 3.0+.
{% macro pagination(total, current, url, nearbyPagesLimit = 4) %}
{% apply spaceless %}
{% if total > 1 %}
<div class="row">
<div class="col">
<div class="pagination-area">
{% if current > 1 %}
<a class="prev page-numbers" href="{{ (url ~ (current-1))|e }}">Prev</a>
{% endif %}
{% for i in 1..total %}
{% if 0 == (current - nearbyPagesLimit) - loop.index %}
<a class="page-numbers" href="{{ (url ~ 1)|e }}">1</a>
{% if 1 != loop.index %}
<span class="page-numbers">...</span>
{% endif %}
{% elseif 0 == (current + nearbyPagesLimit) - loop.index and (current + nearbyPagesLimit) < total %}
<span class="page-numbers">...</span>
{% elseif 0 < (current - nearbyPagesLimit) - loop.index %}
{% elseif 0 > (current + nearbyPagesLimit) - loop.index %}
{% else %}
{% if current == loop.index %}
<span class="page-numbers current" aria-current="page">{{ loop.index }}</span>
{% else %}
<a class="page-numbers" href="{{ url ~ loop.index }}">{{ loop.index }}</a>
{% endif %}
{% endif %}
{% endfor %}
{% if current != total and (current + nearbyPagesLimit) < total %}
<a class="page-numbers" href="{{ (url ~ total)|e }}">{{ total }}</a>
{% endif %}
{% if current < total %}
<a class="next page-numbers" href="{{ (url ~ (current+1))|e }}">Next</a>
{% endif %}
</div>
</div>
</div>
{% endif %}
{% endapply %}
{% endmacro %}
{{ _self.pagination(total, current, url) }}
Updated.
Dropping page number for page no. 1.
BEFORE:
www.example.com/articles/page-1
www.example.com/articles/page-2
www.example.com/articles/page-3
NOW:
www.example.com/articles/
www.example.com/articles/page-2
www.example.com/articles/page-3
{% macro pagination(total, current, url, nearbyPagesLimit = 4) %}
{# Create "main_url" variable with link for the first page #}
{% set foo = url|split('/') %}
{% set foo = foo|slice(0, -1) %}
{% set main_url = foo|join('/') ~ "/" %}
{% apply spaceless %}
{% if total > 1 %}
<div class="row">
<div class="col-md-12 blog-posts">
<nav>
<ul class="pagination theme-colored2">
{% if current > 1 %}
<li><a class="prev page-numbers" href="{{ (url ~ (current-1))|e }}/">«</a></li>
{% endif %}
{% for i in 1..total %}
{% if 0 == (current - nearbyPagesLimit) - loop.index %}
<li><a class="page-numbers" href="{{ (url ~ 1)|e }}/">1</a></li>
{% if 1 != loop.index %}
<li><a href="#"><span class="page-numbers">...</span></a></li>
{% endif %}
{% elseif 0 == (current + nearbyPagesLimit) - loop.index and (current + nearbyPagesLimit) < total %}
<li><a href="#"><span class="page-numbers">...</span></a></li>
{% elseif 0 < (current - nearbyPagesLimit) - loop.index %}
<!-- #1 -->
{% elseif 0 > (current + nearbyPagesLimit) - loop.index %}
<!-- #2 -->
{% else %}
{% if current == loop.index %}
<li class="active"><a href="#"><span class="page-numbers" aria-current="page">{{ loop.index }}</span></a></li>
{% else %}
{% if loop.index == 1 %}
<li><a class="page-numbers" href="{{ main_url }}">{{ loop.index }}</a></li>
{% else %}
<li><a class="page-numbers" href="{{ url ~ loop.index }}/">{{ loop.index }}</a></li>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% if current != total and (current + nearbyPagesLimit) < total %}
<li><a class="page-numbers" href="{{ (url ~ total)|e }}/">{{ total }}</a></li>
{% endif %}
{% if current < total %}
<li><a class="next page-numbers" href="{{ (url ~ (current+1))|e }}/">»</a></li>
{% endif %}
</ul>
</nav>
</div>
</div>
{% endif %}
{% endapply %}
{% endmacro %}
{{ _self.pagination(total, current, url) }}
@Qrzysio you're missing a </nav>
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>