Render twig component in a loop - php

objective : products database + twig component rendered in a loop.
I have this setup:
A .twig product component with my component markup:
<article class="productCard "><h3 class="productCard__name">{{ product.name }}</h3></article>
A loop in my page which I want to display all the instances of the product but with the twig component template:
{% for product in products %}
<div class="col">
{{ include('components/productCard.html.twig'),{'product.name': product.name}) }}
</div>
{% if loop.index % 4 == 0 %}
</div><div class="row" >
{% endif %}
A Database with the actual list of product.
I'm not sure of the correct syntax of the loop call to achieve what I want (passing the parameters of the database to the loop to the component).

The proper syntax would be:
{% include 'components/productCard.html.twig' %}
No need for using with or passing variables. Then your other snippet should work as-is:
<article class="productCard">
<h3 class="productCard__name">{{ product.name }}</h3>
</article>

Related

Twig : how to check if there's a request ? (looking for symfony 5 : app.request)

I'm trying to check through Twig if there is a request in order to show the results of my searchBar, in Twig, ONLY if there is a request.
I found old symfony docs on app.request, but it doesn't seem to work for my 5.2 Symfony Project (here is my twig template) :
{% if app.request %}
<h3 class="main-header_h3">Résultats de la recherche</h3>
<hr>
<div class="grid">
{% for product in products %}
{% include 'product/_card.html.twig' with {product: product} only %}
{% endfor %}
</div>
<hr>
{%endif %}
Problem here is that my {% if app.request %} isn't being interpreted, so I get my whole product database coming on my view.
If you need any more code, let me know (Controller/Repository...) but the request definitely works, it's just my rendering in Twig that gives me trouble using that if.
Thanks to #bechir, the solution to checking if my URL has a 'search' parameter in it using TWIG is :
{% if app.request.query.get('search', null) %} where search is the
url parameter. (from : bechir)
So this is what it now looks like, and I do have my partial product/_card.html.twig loaded only when there's a URL parameter search:
{% if app.request.query.get('search', null) %}
<h3 class="main-header_h3">Résultats de la recherche :</h3>
<hr>
<div class="grid">
{% for product in products %}
{% include 'product/_card.html.twig' with {product: product} only %}
{% endfor %}
</div>
<hr>
{% endif %}

Next article section not working in craftcms anyone know what went wrong here?

one of my craft cms projects, I have articles and once click articles I can read those articles, and in that right side content I have a tab call Next article, but when clicking that nothing response
here the live site - http://ambitmagazine.co.uk/poems/ambit-poetry-competition-2018
screenshot - https://prntscr.com/o9gkph
_entry.html
{% extends "_layout" %}
{% block content %}
{% set issue = entry.issue.first() %}
{% set nextArticle = craft.entries.section('articles').after(entry.postDate).order('postDate asc').limit(1).find() %}
<div class="article section{% if entry.largeText %} article--larger-text{% endif %}">
<div class="article__inner section__inner">
{% include 'articles/_partials/article-header' with { article: entry, issue: issue } only %}
{% include "articles/_types/" ~ entry.type %}
{% if entry.relatedAuthor|length > 0 %}
{% include 'articles/_partials/article-footer' with { article: entry } only %}
{% endif %}
{% if nextArticle|length > 0 %}
<div class="next-item">
<a href="{{nextArticle[0].url}}" class="next-item__inner">
<span><strong>Next Artcile</strong></span>
<span>\</span>
<span>{{nextArticle[0].title}}</span>
</a>
</div>
{% endif %}
<div class="article__sidebar-inner"></div>
</div>
<div class="article__sidebar-outer"></div>
</div>
.after is doing a >= operation so the current article is included in the results, and is almost certainly going to be the first option.
Doing something like .after(entry.postDate|date_modify('+1 second')) will exclude the current article and should give you what you are looking for.
It may be more clear for your query to keep the time as is, but explicitly exclude the current entry by id:
{% set nextArticle = craft.entries()
.section('articles')
.after(entry.postDate)
.id(['not', entry.id])
.order('postDate asc')
.one() %}

Twig loop. control class names

Im trying in Twig to set different classes depending on how may items that gets rendered. Eg, if only one, if only two, if only three etc I want to set a different class on the item. How would I do that?
<ul>
{% for item in items %}
<li>
{% include 'components/list/person.twig' with item %}
</li>
{% endfor %}
</ul>
If you want to know in advice the length of the loop, you can use the predefined loop variable that is named length:
loop.length: The number of items in the sequence
as example:
{% for user in users %}
{{ loop.index }}/{{ loop.length }} - {{ user.username }}
{% endfor %}
hope this help
I am not sure that i understood your question or not...
But if you want to use different classes on base of index of loop then you can use loop.index in loop.
Hope this will help you
<ul>
{% for item in items %}
{℅ if loop.index == 1 ℅}
// Set class here
{℅ endif %}
<li>
{% include 'components/list/person.twig' with item %}
</li>
{% endfor %}
</ul>

Twig loop for nested comment in a Symfony-Doctrine blog

I am trying to implement a comment section on a blog with Symfony and Doctrine, using Twig templates.
I am having some trouble trying to implement a response system for my comments. I would like to have something like this:
<div class="comment">
<p>This is comment number 1</p>
<div class="response">
<p>This is a response to comment number 1</p>
<div class="response">
<p>This is a response to response just above</p>
</div>
</div>
</div>
So I would like to have sort of a nested comment system.
I have a Comment entity with a $response property having a OneToOne Relation with another Comment entity:
/**
* #ORM\OneToOne(targetEntity="Comment")
*/
protected $response;
In my controller, I just get my comments like this:
$comments = $this->getDoctrine()
->getManager()
->getRepository('AppBundle:Comment')
->findByArticle($article);
Now I am trying to create the HTML (Twig) but I don't know how to loop throught all comment and associated response so I can create the HTML as I wrote just above...
Anyone who can help me with that?
Thanks.
All you need is recurrence. You have a few options to choose from, one of them is using a macro.
Create twig file with your macro:
{# src/AppBundle/Resources/views/Default/_macro.html.twig #}
{% macro print_comments_recursively(comment) %}
<div class="response">
<p>{{ comment }}</p> {# implement __toString on your Comment class or print appropriate property #}
{% if comment.response is not null %}
{{ _self.print_comments_recursively(comment.response) }}
{% endif %}
</div>
{% endmacro %}
Import macro in your view and use it:
{% import 'AppBundle:Default:_macro.html.twig' as macros %}
<div class="comment">
<p>{{ comment }}</p>
{% if comment.response %}
{{ macros.print_comments_recursively(comment.response) }}
{% endif %}
</div>
Here you have similar problem, already solved, with other solutions: How to render a tree in Twig

Customising form rows in a collection form field

I am trying to customise a specific form row in my form layout. From the symfony cookbook it tells me, if i understand correctly, that I can modify the form by adding a code block in my form theme file.
I am adding the field to the form like this:
->add('editions', 'collection',
array('type' => new EditionType(),
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
)
)
I generate the form rows in the template in the following way, I need the data-prototype tag because the user needs to possibility to add an edition when viewing the form:
<div class="editions" data-prototype="{{ form_widget(form.editions.vars.prototype)|e }}">
{% for edition in form.editions %}
<section class="edition-container">
{{ form_label(edition.isbn) }}
{{ form_errors(edition.isbn) }}
{{ form_widget(edition.isbn) }}
</section>
{% endfor %}
</div>
To customise the rows for the 'editions' fields I tried the following:
<!-- Custom form theme for textarea label rows -->
{% block textarea_label %}
{% spaceless %}
<div {{ block('label_container_attributes') }}>
<label class="label">{{ label }}</label>
</div>
{% endspaceless %}
{% endblock %}
<!-- Custom form theme for edition field textarea label rows -->
{% block _booklist_editions_label %}
{% spaceless %}
<div {{ block('label_container_attributes') }}>
<label class="label">{{ label }}!</label>
</div>
{% endspaceless %}
{% endblock %}
Unfortunately the second block isn't working, the first block however does work. What I did notice is that the outer div from the editions field does not have an id attribute with the field name in it.
This makes me think that the solution to the problem could be one of these:
Custom form theme block has the wrong name, don't know what other name I should give it then.
The id's is not added to the outer div, therefor it's not 'linking' the custom form style.
Could someone explain me how I can add a custom form theme to my 'editions' field using an external form theme file or how I can achieve this in another way.

Categories