Skip to content

Instantly share code, notes, and snippets.

@maxpou
Last active February 26, 2023 20:28
Show Gist options
  • Star 23 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save maxpou/612359ed4af4cc5c4f06 to your computer and use it in GitHub Desktop.
Save maxpou/612359ed4af4cc5c4f06 to your computer and use it in GitHub Desktop.
Example of pagination with Twig
{#
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 %}
@Qrzysio
Copy link

Qrzysio commented Apr 20, 2020

Correct. Thanks a lot. I've updated the code.

@skylord123
Copy link

{% 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.

@cadot-info
Copy link

thanks, for your share ;-)

@cadot-eu
Copy link

cadot-eu commented Apr 20, 2022

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">&laquo;</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">&raquo;</span>
				</a>
			</li>
		</ul>
	</nav>

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