How to limit knp_paginator from extending? - symfony

I want to limit the pagination boxes going for ever. Say there is 100 events loaded -> 3 events are displayed/page; and such that the pagination boxes [1][2][3][4]....[40] doesn't go on...

In config.yml add this:
knp_paginator:
page_range: 5 # number of links showed in the pagination menu (e.g: you have 10 pages, a page_range of 3, on the 5th page you'll see links to page 4, 5, 6)
If you need change the sliding use any of these:
template:
pagination: '#KnpPaginator/Pagination/sliding.html.twig'
#KnpPaginator/Pagination/sliding.html.twig (by default)
#KnpPaginator/Pagination/twitter_bootstrap_v3_pagination.html.twig
#KnpPaginator/Pagination/twitter_bootstrap_pagination.html.twig
#KnpPaginator/Pagination/foundation_v5_pagination.html.twig

I guess that knp paginator does that for you but in case it does not You could try to modify any of the templates above to do something like this:
set a control variable
{% if pageCount > maxNumberOfBoxes %}
{% set breakpointAdded=true %}
{% endif %}
then find the loop which look like this
{% for page in pagesInRange %}
{% if page != current %}
<span class="page">
{{ page }}
</span>
{% else %}
<span class="current">{{ page }}</span>
{% endif %}
{% endfor %}
and replace it for something like this(with your own logic of course)
{% for i in range(0,pageCount) %}
{% if i > xBreakpoint and i < yBreakpoint and breakpointAdded == false %}
<span class="dots">...</span>
{% set breakpointAdded = true %}
{% else %}
{% if page != current %}
<span class="page">
{{ page }}
</span>
{% else %}
<span class="current">{{ page }}</span>
{% endif %}
{% endif %}
{% endfor %}
if anything of this works you could try to modify the getPaginationData function from SlidingPagination class.
what ever works for you.

Related

Twig3: How to migrate "for item in items if item.foo == 'bar'" with loop bariable

I use the following Twig 2 code:
{% for item in items if item.foo == 'bar' %}
<span class="{% if loop.index % 2 %}special-class{% endif %}">
{{ item.value }}
</span>
{% else %}
Nothing found
{% endfor %}
In the twig docs: https://twig.symfony.com/doc/2.x/deprecated.html
Adding an if condition on a for tag is deprecated in Twig 2.10. Use a filter filter or an "if" condition inside the "for" body instead (if your condition depends on a variable updated inside the loop)
I wonder how I migrate my Twig 2 code to Twig 3. As you see I use the loop variable and else in the for loop. I know that I can use a new parameter and increase it myself... but it that really the intention? How do I rewrite this code using filter?
You have two options to solve this
Place the if-tag inside the loop
{% set i = 0 %}
{% for item in items %}
{% if item.foo == 'foo' %}
<span class="{% if i % 2 %}special-class{% endif %}">
{{ item.value }}
</span>
{% set i = i + 1 %}
{% endif %}
{% else %}
Nothing found
{% endfor %}
With this solution you can't "rely" on the internal loop variable, as the counter keeps going up whether or not the condition was met
Use the filter - filter
{% for item in items | filter(item => item.foo == 'foo') %}
<span class="{% if loop.index % 2 %}special-class{% endif %}">
{{ item.value }}
</span>
{% else %}
Nothing found
{% endfor %}
updated demo
Using the filter filter your code would look something like this (see also https://twigfiddle.com/9hiayc and https://twigfiddle.com/9hiayc/2):
{% for item in items|filter(i => i.foo == 'bar') %}
<span class="{% if loop.index % 2 %}special-class{% endif %}">
{{ item.value }}
</span>
{% else %}
Nothing found
{% endfor %}

How to change "if" condition related to a page

I would like to include tab_system.twig file in two differents files : archive.twig and blog_list.twig to have the same html in those two files.
{% include "tab_system.twig" %}
In this tab_system.twig file I have a condition to add the active class :
{% if XXX %}active{% endif %}
But this condition must be different depending on which page the user is.
For blog_list.twig :
{% if loop.first %}active{% endif %}
For archive.twig :
{% if item.term_id == term_page.term_id %}active{% endif %}
I wrote this without success :
{% set addclass = '' %}
{% if is_blog_list %}
{% set addclass = '{% if loop.first %}active{% endif %}' %}
{% elseif is_archive %}
{% set addclass = '{% if item.term_id == term_page.term_id %}active{% endif %}' %}
{% endif %}
In tab_system.twig I have a tab system with menu from a part and content to the other part. I wrote a js loop to display the corresponding content. I need to add active class on the first link and first content tab in blog_list.twig file and to add active class to the link and content tab depending on which category the user is.
<div class="tab-menu-list">
{% for item in all_posts %}
<a href="#" class="tab-menu {{ addclass }}"</a>
{% endfor %}
</div>
<div class="tab-content-list">
{% for item in all_posts %}
<div href="#" class="tab-content {{ addclass }}"</div>
{% endfor %}
</div>
is_archive and is_blog_list are variables defined elsewhere. They work
How can I create a condition ? Thank you in advance.
As I'm assuming you are looping the records, I'd say don't overcomplicate things,
single.twig
{% for i in 1..5 %}
{% include 'article.twig' with { 'active' : loop.first, } %}
{% endfor %}
template_blog.twig
{% for item in items %}
{% include 'article.twig' with { 'active' : item.term_id == term_page.term_id, } %}
{% endfor %}
article.twig
<div class="articles__list tab-content{{ active ? ' active'}}">
foo
</div>
demo - just change the main template
If you really wanted to keep that for inside the article template, which I think is not a great idea, you could still use the variables is_archive and is_blog_list inside article, e.g.
article.twig
{% for item in items %}
{% if is_archive %}
{% set active = loop.first %}
{% elseif is_blog_list %}
{% set active = item.term_id == term_page.term_id %}
{% endif %}
<div class="articles__list tab-content{{ active ? ' active'}}">
{% endfor %}

Django CMS conditional

How do I use a conditional in Django CMS in base.html to detect if the page is the home page and add a unique class to the body tag? I'd prefer to not duplicate base and just add a class so I can handle some styles differently on the home page.
It depends how you structure your pages.
I opt for creating pages as a child of the 'home' page so use something like this for page titles;
{% if request.current_page.get_ancestors|length <= 1 %}
<h1>{{ request.current_page.get_page_title }}</h1>
{% else %}
{% for ance in request.current_page.get_ancestors %}
{% if ance.depth == 2 %}
<h1>{{ ance.get_page_title }}</h1>
{% endif %}
{% endfor %}
{% endif %}
So you could do something like;
<body class="{% if request.current_page.get_ancestors|length <= 1 %}base{% endif %}">

Using a counter in a Twig node template

Setting up a Drupal 8 custom view for Top 4 items, I want a different layout for item 1 than the remaining. I have override files for the custom view, but for this example I'm using base files to keep it simple.
In views-view.html.twig base file we have:
<div class="view-content">
{{ rows }}
</div>
In node.html.twig base file we have:
<div {{ content_attributes.addClass('content') }}>
{{ content }}
</div>
In node.html.twig I am aiming for something like:
{% if row_counter = 1 %}
output this markup / fields
{% else %}
do something boring with the other 3 items.
{% endif %}
I was able to set row_counter in the views-view.twig.html file:
{% for row in rows %}
{% set row_counter = loop.index %}
<div{{ row.attributes }}>
{{ row_counter }}
</div>
{% endfor %}
But I need to check against the value of {{ row_counter }} in the node.html.twig file....
What other properties are available in node.html.twig to check against its position in the list?
From the documentation
The loop variable
Inside of a for loop block you can access some special variables:
Variable Description
-----------------------------------------------------------------
loop.index The current iteration of the loop. (1 indexed)
loop.index0 The current iteration of the loop. (0 indexed)
loop.revindex The number of iterations from the end of the loop (1 indexed)
loop.revindex0 The number of iterations from the end of the loop (0 indexed)
loop.first True if first iteration
loop.last True if last iteration
loop.length The number of items in the sequence
loop.parent The parent context
edit: every variable know in the parent template is also known inside an include as context is passed by default. Only macro's don't know the parent's context
controller
<?php
require __DIR__ . '/../requires/propel_standalone.php';
echo $twig->render('tests/items.html', [
'items' => [
'Abc',
'def',
'ghi',
'jkl',
'mno',
'pqr',
'stu',
'vwx',
'z',
],
]);
items.twig
<!doctype>
<html>
<head><title>Test</title></head>
<body>
{% for item in items %}
{% include "tests/item.html" %}
{% endfor %}
</body>
</html>
item.twig
{% set order = 'Nothing to report' %}
{% if loop.first %}
{% set order = 'I\'m first' %}
{% endif %}
{% if loop.last %}
{% set order = 'I\'m last' %}
{% endif %}
{% if loop.index is even %}
{% set order = 'I\'m even' %}
{% endif %}
{% if loop.index is divisible by(5) %}
{% set order = 'I can be dived by 5' %}
{% endif %}
{% if loop.index is divisible by(3) %}
{% set order = 'I can be dived by 3' %}
{% endif %}
<div>
<b>{{ loop.index }}:</b>{{ order }} - {{ item }}
</div>
You could do something like this if a class is enough:
Your views template:
{% for row in rows %}
<div class="{% if loop.index == 1 %}first_element{% endif %}">
{{ row.content }}
</div>
{% endfor %}
And then just style it appropriately.

Twig, how to print a nl2br output in one line

I used the nl2br filter like this:
{{ knp_pagination_render(requests)|raw|nl2br}}
It prints the html object separated by a few line breaks, and I need to print all the objects in one single line. How can I reach that?
Any help would be great.
{{ string | replace({"\\n":""}) }}
See fiddle.
I suggest you to override the default pagination template, so you can customize how to generate the underling HTML code.
As described in the doc You can do simply:
{{ knp_pagination_render(request, 'MyBundle:Pagination:pagination.html.twig') }}
You can copy the current pagination implementation from here and customize it as you need.
This is the default implementation:
{# default Sliding pagination control implementation #}
{% if pageCount > 1 %}
<div class="pagination">
{% if first is defined and current != first %}
<span class="first">
<<
</span>
{% endif %}
{% if previous is defined %}
<span class="previous">
<
</span>
{% endif %}
{% for page in pagesInRange %}
{% if page != current %}
<span class="page">
{{ page }}
</span>
{% else %}
<span class="current">{{ page }}</span>
{% endif %}
{% endfor %}
{% if next is defined %}
<span class="next">
>
</span>
{% endif %}
{% if last is defined and current != last %}
<span class="last">
>>
</span>
{% endif %}
</div>
{% endif %}

Resources