Access to an array field - symfony

I have a real strange problem with twig, I iterate over an array and when I try to 'print' value with {{value}} I get the exception "Array to string conversion" and when I try with {{value.first()}} I get the error "Impossible to invoke a method ("first") on a string variable ("false")"
Can someone help me out ?
<select name="select">
{% for key,value in array %}
{% if (key != 'id') and (key != 'type') %}
<option value={{key}}>{{ key }}: {{ value }}</option>
{% endif %}
{% endfor %}
</select>

I think the best way to handle this would be to pass the data already flatten to Twig, so it would only need to loop through the data always in the same way.
If that's not possible and you need to use Twig to handle this, you can make use of iterable. This is not pretty, but here we go:
<select name="select">
{% for key,value in array %}
{% if (key != 'id') and (key != 'type') %}
{% if value is iterable %}
{% for item in value %}
<option value={{item}}>{{ key }}: {{ item }}</option>
{% endfor %}
{% else %}
<option value={{key}}>{{ key }}: {{ value }}</option>
{% endif %}
{% endif %}
{% endfor %}
</select>

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 %}

Twig template set select control to database value

I have a class called Offices which contains id and officeName among other attributes.
I'm trying to fill a select control with all possible values for that class and then set the select control to the value for the current record (stored as customer.officeName)
{% for office in offices %}
<option value="{{ office.Id}}">{{ office.officeName}} </option>
{% if %}
(office.id== customer.officeName) ? ' selected ' : ''
{% endif %}
{% endfor %}
</select>
Any suggestions on how I can update the above syntax to work?
Figured it out
this works
{% for office in offices %}
<option value="{{ office.Id}}"
{% if (office.Id== customer.managingOffice) %}
{{ 'selected'}}
{% endif %}
>{{ office.officeName}}</option>

Is it possible to override default # products in a row in custom Shopify collections template?

I have created an alternate collection.liquid template for a shopify site I'm working on. My struggle is with not being able to control the number of products that appear in a row in the grid. I developed the custom template so that I wouldn't affect the number of products/row that appear on the other collections.
The code that displays the grid in my liquid template is this:
<div class="four columns section_select {% unless settings.collection_sort %}offset-by-four omega{% endunless %}">
{% for tag in collection.all_tags %}
{% if forloop.first %}
<label for="tag_filter" class="inline">
{{ 'collections.sorting.filter' | t }}: </label>
<select name="tag_filter" id="tag_filter">
<option {% unless current_tags %}selected="selected"{% endunless %} value="{% if collection.handle == "all" %}/collections/all{% else %}{{ collection.url }}{% endif %}">{{ 'collections.general.all_collection_title' | t: title: collection.title }}</option>
{% endif %}
{% unless tag contains 'meta-related-collection-' %}
<option {% if current_tags contains tag %}selected="selected"{% endif %} value="/collections/{% if collection.handle != blank %}{{ collection.handle }}{% else %}all{% endif %}/{{ tag | handleize }}">{{ tag }}</option>
{% endunless %}
{% if forloop.last %}
</select>
{% endif %}
{% endfor %}
</div>
Even when I change the class class="four columns" to something else, it is not reflected on my collection.
The problem could be in my code that assigns how many products are pulled in this collection but I can't seem to make a difference.
{% case products_per_row %}
{% when '1' %}
{% assign grid_item_width = 'medium--one-third large--one-whole' %}
{% when '2' %}
{% assign grid_item_width = 'medium-down--one-half large--one-half' %}
{% when '3' %}
{% assign grid_item_width = 'medium--one-third large--one-third' %}
{% when '4' %}
{% assign grid_item_width = 'medium-down--one-half large--one-quarter' %}
{% when '5' %}
{% assign grid_item_width = 'medium-down--one-half large--one-fifth' %}
{% endcase %}
Any help would be great!
It looks like your theme is using Timber grid.
You will find grid structure and classes to use in documentation here: https://shopify.github.io/Timber/
HTH

Twig compare two values in different arrays

First of all I'm learning Twig.
I was wondering if it is possible wit Twig to compare two different values from different arrays/lists?!
I have two list of items I call them like so:
{% if page.cart %}
{% for product in page.cart.products %}
{{ product.id }}
{% endfor %}
{% endif %}
And:
{% if products %}
{% for product in products %}
{{ product.id }}
{% endfor %}
{% endif %}
I want to compare both product.id's so I can create a new statement. Is there any way to compare both values? The idea is to check if an id is present in page.cart.products and if so then do something.
I want to create a new statement to display some info. Something like so:
{% if page.cart %}
{% for product in page.cart.products %}
{% set cartId %}{{ product.id }}{% endset %}
{% endfor %}
{% endif %}
{% if products %}
{% for product in products %}
{% set listId %}{{ product.id }}{% endset %}
{% endfor %}
{% endif %}
{% if cartId == listId %}
.... do this ....
{% endif %}
Any help greatly appreciated!
You can loop over one array and check if the id is present in the second one. If it's there, you can do something.
{# In case you want to store them, you can do so in an array #}
{% set repeatedIds = [] %}
{% for productCart in page.cart.products if page.cart %}
{% for product in products if products %}
{% if productCart.id == product.id %}
<p>This id -> {{ product.id }} is already in page.cart.products</p>
{% set repeatedIds = repeatedIds|merge([product.id]) %}
{% endif %}
{% endfor %}
{% endfor %}
{{ dump(repeatedIds) }}
It's a very basic search algorithm and the cost is quadratic. Obviously, there are more efficient ways to look for an element in an array (though more complicated to implement).
If the amount of products you have to deal with is not very big, you could use this solution. However, if you have, let's say, more than one hundred products in each array (or you feel that the algorithm is slowing down your loading time), you could do this process in the controller using more sophisticated methods and PHP and just pass the result to the template.
Hope it helps.

Get choices from select in twig

I'm new in Symfony2 and Twig, really I only markup the views of some forms. I have created a generic forms.twig.html with some macros for render type of input.
Then I pass to the select type the options list for selects options, but I cant get this options in the vars array from symfony2. ¿Is this possible?
Macro
{% macro select(name, options, selected) %}
<div class="innerB">
<select class="form-control" name="{{name}}">
{% for option in options %}
{% if option.value == selected %}
<option value="{{option.value}}" selected>{{ option.value }}</option>
{% else %}
<option value="{{option.value}}">{{ option.value }}</option>
{% endif %}
{% endfor %}
</select>
</div>
{% endmacro %}
And this is the twig:
<!-- Print selects -->
{% if type == 'choice' %}
{{ macroforms.label(item.vars.name, item.vars.label) }}
{{ macroforms.select(item.vars.name, item.vars.choices, item.vars.selected?) }}
{% endif %}
Updated: This works... The problem was type of element, "choice" and not "collection", but now, I want to access each element for the collection, which are choices... Any idea?

Resources