(Liquid) Checking for a variable in an array - arrays

I’m looking to find if the title of the current collection page exists inside the array of shop.vendors and display a div only if the collection page title does not exist in the array. From the documentation it seems like I should be able to do this but it doesn't work?
{%- unless shop.vendors contains collection.title -%}
<div> display content in here if condition is not met </div>
{%- endunless -%}

So I've found out why this wasn't working, for anyone else who comes across this
shop.vendors renders an ampersand as &amp rather than &, while collection.title renders it as &. Therefore, if you try to compare the names it won't work.
The solution is doing | escape to only shop.vendors so they're formatted the same, then the comparison will work. I also did | remove to get rid of the ampersand entirely as it's not strictly needed in the name comparison in my case.

You can rewrite your code as:
{% for vendor in shop.vendors %}
{% if vendor == collection.title %}
<div> display content in here if condition is not met </div>
{% endif %}
{% endfor %}

Related

How to combine two collections in Shopify liquid without changing it to an array?

I'm trying to sort a collection before rendering it in liquid, with the intention of being able to move all sold out products to the bottom, and have them return to their original position once they are back in stock.
I have previously tried filtering the forloop directly, splitting it into two loops with opposing criteria, but the paginate effectively messes it up and renders my logic per page, instead of on the entire collection. That means the sold out products appear at the bottom of each page.
After learning this, I figured my best bet would be to create two collections and combine them before paginating and rendering, and then paginating the collections based on the new, sorted collection.
Pagination does not accept arrays, which is where I'm stuck. Here is the code I'm trying to sort the collection with:
{% assign topcol = collection %}
{%- for product in topcol.products -%}
{% assign product = null %}
{%- if product.available or product.tags contains "_boost" -%}
{% assign product = product %}
{%- endif -%}{%- endfor -%}
{% assign bottomcol = collection %}
{% assign product = null %}
{%- for product in bottomcol.products -%}
{%- unless product.available or product.tags contains "_boost" -%}
{% assign product = product %}
{%- endunless -%}{%- endfor -%}
{% assign sortedcol = topcol | concat: bottomcol %}
If I then try
{%- paginate sortedcol.products by section.settings.products_per_page -%}
I get an error "Array 'sortedcol.products' is not paginateable." because I made it into an array instead of retaining the collection structure I believe.
Is there a better way to do this? Am I missing something? A split?

Can I call a jekyll page attribute within a for statement

{% for item in site.data.{{page.ocean}}.section %}
This is not working for me. I'm using page.ocean at other places in the page and it works fine. I'm not sure if I can do this within a for statement. If not, is there a way to work around it?
Try this:
{% assign ocean = page.ocean %}
{% for item in site.data[ocean].section %}
<!-- your code -->
{% endfor %}
Check Liquid's Variable and yes we can access data variable content like an Array through indexing.

Shopify For Loop to Blur images if product.tags = 'phrase'

Essentially I want to go ahead and while the for loop is going to get the images and information of all products to be displayed. insert a conditional if statement in order to see if the products tags contain the tag 'lewd' then it's blurred (right now it's set to just not display the image though)
I'm having issues finding the best place to implement it, I know it should be done on the product templates page (I think) because it seems to be pulling the images and information in the loop, but no matter where I insert the code to try to pull the info and apply the effect it doesn't work. I've gone through many many different ways to do it and this is only the latest example.
<div class="grid product-single{% if section.settings.enable_payment_button %} product-single--{{
section.settings.image_size }}-image{% endif %}">
<div class="grid__item product-single__photos {{ product_image_width }}{% if
section.settings.image_size == 'full' %} product-single__photos--full{% endif %}">
{%- assign featured_image = product.selected_or_first_available_variant.featured_image | default:
product.featured_image -%}
{% for image in product.images %}
{% capture img_id %}FeaturedImage-{{ section.id }}-{{ image.id }}{% endcapture %}
{% capture img_class %}product-featured-img{% endcapture %}
{% capture zoom_img_id %}FeaturedImageZoom-{{ section.id }}-{{ image.id }}{% endcapture %}
{% capture img_wrapper_id %}{{ zoom_img_id }}-wrapper{% endcapture %}
{%- assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
{% include 'image-style' with small_style: true, width: height, height: height, wrapper_id:
img_wrapper_id, img_id: img_id %}
<div id="{{ img_wrapper_id }}" class="product-single__photo-wrapper js">
Before the loop closes I want to go ahead and search for those tags so my code was
{% if product.tags contains "Lewd" or product.tags contains "lewd" %} blur {% endif %}
I'm not sure if Shopify already passes this info along though? in that case I suppose i would need to run another forloop? Such as
{% for tag in product.tags %}
{% if tag contains "lewd" %}
but not sure where i would even do that. I'm a novice at working with shopify. thanks for any help
The contains keyword behaves slightly differently depending on what you're using it on:
If the left-hand-side variable is a text string, contains will return true if the right-hand-side value is found as a substring of the left-hand-side value.
If the left-hand-side variable is an array, contains will return true if one of the array values exactly matches the value supplied on the right-hand-side. Type matters, too - a number won't match a string, a string won't match an object, etc.
product.tags gives you an array of strings, so as long as the product has a tag that is exactly lewd then your intuition is correct: {% if product.tags contains 'lewd' %} will be true. However, if your product is tagged with something like lewd-because-reason instead (and doesn't have a plain 'lewd' tag), lewd-because-reason is not an exact match to lewd, so the check above would be false.
Looking at the code you've supplied, a good place to put this check could be inside the {% capture img_class %} line, as then you should be able to add another class to the image being rendered.
Hope this helps!

Drupal 8 - how to access field values nested deep inside an array structure

I am trying to access values of a content type nested deep into array. This is the actual scenario:
I want to customise the default search result page layout of Drupal 8 with additional field information. To know what fields are available for me to access I used {{ kint(item.value) }}, which shows me this:
Fields I want to access are nested under #result>node>fields like body, field_category etc.
Is there any way I can access them directly inside my twig template? I was guessing something like {{ item.value['node']['fields']['field_name']} }? but this gave me nothing!
There is every possibility that the way I am thinking is not a suitable method or may be even not a method at all! I am still very new to Drupal.
All I want is to access desired fields nested deep below inside an array structure. Is there a kind of thumb rule or syntax to follow? This would be a great help if somebody please explain the process to access a specific element from inside a nested Drupal array.
Note: In order to customise layout I copied item-list.html.twig file from /core/themes/stable/templaes/dataset to my theme's templates folder.
Drupal version: 8.2.3
EDIT: Template file for search result (item-list.html.twig)
<p class="righteous">Makes sure the page is being hit!</p>
{% if context.list_style %}
{%- set attributes = attributes.addClass('item-list__' ~ context.list_style) %}
{% endif %}
{% if items or empty %}
{%- if title is not empty -%}
<h3>{{ title }}</h3>
{%- endif -%}
{%- if items -%}
<{{ list_type }}{{ attributes }}>
{%- for item in items -%}
<li{{ item.attributes }}>{{ content.body }}</li>
{%- endfor -%}
</{{ list_type }}>
{%- else -%}
{{- empty -}}
{%- endif -%}
{%- endif %}
If you want to render specific fields from a template you have to use for example:
{{ content.field_feature }}
you can see in your array or in the UI of d8 the machine names of your fields.
{{ content.field_<machine-name> }}
with this you can access your array and theme your content type yourself.

Jinja2 : declaring and saving array

I am new to Jinja2 and I was forced to use it for a custom web application. I want to declare an array and save values to it. Can someone suggest me where I am going wrong?
{%- for row in doc.other_charges -%}
{%- if not row.included_in_print_rate -%}
{% set data[i]=row.description %}
{% i++ %}
{% set data[i]=row.get_formatted("tax_amount", doc) %}
{% i++ %}
{%- endif -%}
{%- endfor -%}
You have two problems:
Your data variable is declared inside the for loop and not available to the outer scope.
There is no ++ operator in Python.
But the main issue is that, you should actually have business logic inside your views and presentation in your templates. Even if you find a workaround to make your example work, you should still move your logic to the view that generates the context variables to be consumed by your template. Your templates must be simple enough to be left alone when a business requirement change.

Resources