How can I downcase array of a looped article.tags in Shopify liquid code - shopify

I am trying to loop over the articles in a blog to see if the article.tags contains any of the value in taggs where taggs is an array to be supplied by the user. I want to retrieve an array of related articles by tag.
Below is my example code:
{% assign taggs = "T-shirt,bag,Purse,Handbag" | split: "," %}
{%- assign length = b_s.related_article_blog_count | plus: 0 -%}
{% capture fourthtag %}{{ taggs[3] | downcase }}{% endcapture %}
<div class="jj-post-content">
<div class="item">
{%- for article in blogs[blog].articles limit: length -%}
{% if article.tags contains fourthtag %}
<a href="{{ article.url }}">
<div class="jj-title">{{ article.title }}</div>
</a>
{%- endif -%}
{%- endfor -%}
</div>
</div>
When I run the code it returns no result. But when I created the article tags in lowercase, I got all the articles filtered as expected. Given that many of the users may not be creating tags in lowercase, I need a way to downcase the article.tags from the loop.
I tried {% capture atc %}{{ article.tags | downcase }}{% endcapture %} before the loop but it was not working.

I came up with this. Make a string, normalize the strings to remove as many oddities as possible, remake into an array to use with iteration.
{%- assign normalized_article_tags = article.tags | join:"," | downcase | split:"," %}
{% if normalized_article_tags contains fourthtag %}
You should also strip excess whitespace, end of lines, html and or handleize the tags to further normalize data being matches to potentially ambiguous user data.
Further
{% capture fourthtag %}{{ taggs[3] | downcase }}{% endcapture %}
can become
{% assign fourthtag = taggs[3] | downcase %}
Try to reserve using capture for outputs that will be repeated , such as snippets rendering , trying to do a kind of pseudo-interpolation, or long form text that would be obnxious to use with only an assign statement. https://shopify.dev/api/liquid/tags/variable-tags#capture

Related

Shopify Liquid tag nested in liquid tag - any workaround?

I'm new to Shopify and Liquid. I know that you can't nest a liquid tag within another liquid tag ie:
{% something {{ something_else }} %}
I was wondering if there is a workaround for this kind of scenario? Possibly involving 'capture' or clever use of 'raw'?
I'm building a site that uses product tags to denote which chocolates go in which products (collection of chocolates). On the product page I can easily return the tags as a list:
<ul class="chocolates-menu">
{% for tag in product.tags %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
However, I'd like to render snippets with file names to match the names of the tags (these will contain an image, chocolate name and chocolate description) ie:
<li>{% render '{{ tag }}' %}</li>
The closest I've got is:
{% for tag in product.tags %}
{% capture chocolate_tag %}
{% raw %}{% render{% endraw %} {% raw %}'{% endraw %}{{ tag }}{% raw %}' %}{% endraw %}
{% endcapture %}
<li>{{ chocolate_tag }}</li>
{% endfor %}
This will output the correct code but as text on the page (rather than parsing it). ie: {% render 'Tag Name Here' %} simply as the text of the list item. Any help from brighter folk, is much appreciated. Thanks.
I would suggest creating a snippet for all your chocolates and using the tag as a variable to output what is needed.
Here is a visual representation of what I mean and is kinda clearer from your discussion with #Fabio Filippi
snippets/chocolate.liquid
{% assign tag_image = tag | append: '.png' %}
{% case tag %}
{% when 'diet' %}
<img src="{{ tag_image | file_img_url: '100x' }}" class="responsive" />
{% when 'dark' %}
<div>My dark chocolate HTML</div>
{% when 'white' %}
<div>My white chocolate HTML</div>
{% endcase %}
and how to use:
{% render 'chocolate', tag: tag %}

Adding preview of Non-featured image in Shopify / Liquid

On Shopify, product cards display 'featured media' (i.e. the first image of all of its images) using the following liquid code (this is using the default Shopify theme).
{% capture img_id %}ProductCardImage-{{ section.id }}-{{ product.id }}{% endcapture %}
{% capture wrapper_id %}ProductCardImageWrapper-{{ section.id }}-{{ product.id }}{% endcapture %}
{%- assign preview_image = product.featured_media.preview_image -%}
{%- assign img_url = preview_image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
{% unless preview_image == blank %}
{% include 'image-style', image: preview_image, height: max_height, wrapper_id: wrapper_id, img_id: img_id %}
{% endunless %}
I want to display another image (e.g. the second one) when hovering over the product, meaning I need to be able to call a different image and not just the featured image.
How would I change the code from product.featured_media to instead call a different image?
Thanks a lot!
You can use product.media attribute to access all the media items assigned to products.
This is an array so you can use loops e.g.
{% for media in product.media %}
{{ media | img_tag }}
{% endfor %}
Consequently, you can access the second media using product.media[1].
Useful links:
Media filters
Adding media to themes

Liquid. Looping through an array with an if condition then want to store the output of that in another array

{% assign leg = {{Predept.legs}} %}
{% for legs in {{leg}} %}
{% if {{leg[forloop.index0].direction}} == 'R' %}
{{leg[forloop.index0].arr_station_name}}
{%endif %}
{%endfor %}
I want to put the output of this for loop into another array. Any ideas?
Welcome, Jeet!
First, you don't ever nest the Liquid tags. Your basic loop should look something like this:
{% assign legs = Predept.legs %}
{% for leg in legs %}
<!-- Cool code & stuff here! -->
{% endfor %}
Now, in Liquid you can only create a new array by using the split filter on a string. We can also create a string by wrapping other commands with the capture tag. Putting that together, we get something like:
{% capture leg_data %}
{% assign legs = Predept.legs %}
{% for leg in legs %}
{% if leg.direction == 'R' %}
{% comment %}Output delimiter if needed {% endcomment %}
{% unless found_one %},{% endunless %}
{% assign found_one = true %}
{{ leg.arr_station_name }}
{% endif %}
{% endfor %}
{% endcapture %}
{% assign leg_data = leg_data | split: ',' %}
That will give us an array of all of our arr_station_name for the desired legs, but you may note that capture is also capturing all of the whitespace in there as well. If we need to prevent that from getting into our nice little array, we can use the whitespace-stripping - character on our tags to control that, giving:
{%- capture leg_data -%}
{%- assign legs = Predept.legs -%}
{%- for leg in legs -%}
{%- if leg.direction == 'R' -%}
{%- comment -%}Output delimiter if needed {%- endcomment -%}
{%- unless found_one -%},{%- endunless -%}
{%- assign found_one = true -%}
{{- leg.arr_station_name -}}
{%- endif -%}
{%- endfor -%}
{%- endcapture -%}
{%- assign leg_data = leg_data | split: ',' -%}
Hope this helps!

Auto formating of a .liquid-file (a Shopify theme file)

I'm editting some 3rd-party code (a Shopify theme) and the code is absolutely unreadable.
Ideally, I would like to be able to auto format .liquid-files, but can't seem to be able to.
My attempt in PhpStorm
I've tried inserting the code in PhpStorm and pressing CMD + Option + l (after doing this), which does something, but makes newlines in random places, like this:
{% unless current_tags %}<h1
class="text-center text-uppercase title-under">{{ 'blogs.general.title_main' | t }}</h1>{% else %}<h1
My Attempt in Atom
In Atom I tried installing atom-beautify, but that didn't recognize the file-type. I can see that others have had my issue as well. Since .liquid share quite a lot with .blade.php, then I tried to see if there was a solution for that format, which resulted in an open thread as well.
I tried looking into adding support for a new language (with atom-beautify), but it got quite time-consuming fast.
My attempt with PrettyDiff.com
This got kinda close. But it's still a hassle, if I have an entire Shopify-theme, to copy the code into that website, before moving it to my editor. If PrettyDiff could absolutely nail the auto formatting, then I might have lived with it, - but it still does something like this:
{% if settings.show_blog_sidebar %}
<div class="col-xl-8 col-lg-8 col-md-12" id="centerColumn">
{% endif %}
What I would like to achieve
To make this crap:
{% unless current_tags %}<h1
class="text-center text-uppercase title-under">{{ 'blogs.general.title_main' | t }}</h1>{% else %}<h1
class="text-center text-uppercase title-under">{{ 'blogs.general.title_result' | t }} {{ current_tags.first | replace: '-', ' ' }}</h1>{% endunless %}
{% for article in blog.articles %}{% if article.excerpt contains "SOMEVAR" %}<p>
test</p>{% capture _article %}{% include "get-content-with-key" content: article.excerpt key: "[SOMEVAR]" %}{% endcapture %}{% capture _title %}{% include "get-content-with-key" content: _article key: "[title]" %}{% endcapture %}{% capture author %}{% include "get-content-with-key" content: _article key: "[author]" %}{% endcapture %}{% capture image %}{% include "get-content-with-key" content: _article key: "[image]" %}{% endcapture %}{% capture content %}{% include "get-content-with-key" content: _article key: "[content]" %}{% endcapture %}{% if _title == '' %}{% assign _title = article.title %}{% endif %}{% if author == '' %}{% assign author = article.author %}{% endif %}
{% if article.comments.size > 0 %}{% assign comment_url = article.url | append: '#comments' %}{% else %}{% assign comment_url = article.url | append: '#addcomment' %}{% endif %}
<div class="{{ grid }}">
...
...
Look like this:
{% unless current_tags %}
<h1 class="text-center text-uppercase title-under">{{ 'blogs.general.title_main' | t }}</h1>
{% else %}
<h1 class="text-center text-uppercase title-under">{{ 'blogs.general.title_result' | t }} {{ current_tags.first | replace: '-', ' ' }}</h1>
{% endunless %}
{% for article in blog.articles %}
{% if article.excerpt contains "SOMEVAR" %}
<p>test</p>
{% capture _article %}
{% include "get-content-with-key" content: article.excerpt key: "[SOMEVAR]" %}
{% endcapture %}
{% capture _title %}
{% include "get-content-with-key" content: _article key: "[title]" %}
{% endcapture %}
{% capture author %}
{% include "get-content-with-key" content: _article key: "[author]" %}
{% endcapture %}
{% capture image %}
{% include "get-content-with-key" content: _article key: "[image]" %}
{% endcapture %}
{% capture content %}
{% include "get-content-with-key" content: _article key: "[content]" %}
{% endcapture %}
{% if _title == '' %}
{% assign _title = article.title %}
{% endif %}
{% if author == '' %}
{% assign author = article.author %}
{% endif %}
{% if article.comments.size > 0 %}
{% assign comment_url = article.url | append: '#comments' %}
{% else %}
{% assign comment_url = article.url | append: '#addcomment' %}
{% endif %}
<div class="{{ grid }}">
...
...
Am I really the first human being on this planet who would like to auto format a .liquid-file?
Use Vim or GVim syntax highlighting and command line flags to reformat your code.
vim -V -se +"filetype plugin indent on|set syntax=liquid|filetype|normal gg=G" -cwq test.liquid
-s is silent mode
-e is execution mode (not normal mode)
+"" executes the string inside the quotes, separated by pipes
-cwq is short-hand for command :wq
filetype is just for debugging
normal gg=G goes to the top of the file and re-indents all the way to the end.
If you are just using Vim as an IDE you just type gg=G in normal (not editor) mode (assuming you have filetype based indentation turned on)
Can't be formatted this way in PhpStorm yet: https://youtrack.jetbrains.com/issue/WI-12782 & https://youtrack.jetbrains.com/issue/WI-39065 - corresponding feature requests to add proper formatting you can vote for.

Shopify - remove store title from products page <title> tag

I am working on a shopify store and I cannot seem to get the code right for removing the store name from only the product pages.
Here is the code:
<title>
{{ page_title }}
{% if current_tags %}{% assign meta_tags = current_tags | join: ', ' %}–
{{ 'general.meta.tags' | t: tags: meta_tags }}
{% endif %}{% if current_page != 1 %} –
{{ 'general.meta.page' | t: page: current_page }}{% endif %}
{% unless page_title contains shop.name %}
{% if template != 'article' %} – {{ shop.name }}{% endif %}{% endunless %}
</title>
I have tried using an if statement above this to change page_title to product_title but it breaks this code and no titles show up on any other pages.
Also this code prevents the store name from coming up on articles. I tried using the same code but replaced it with 'product' and it did not work!
All help is appreciated. Thanks!
Try this: before and after your shop name add an unless, like this:
{% unless template contains 'product' %}
{% unless template contains 'article' %}
– {{ shop.name }}
{% endunless %}
{% endunless %}
Also, you should think about using different lines in your code, makes things more readable. Also, using contains instead of = is more foolproof, so I took the liberty of changing that for you
Found the solution ... an if/else statement. I thought I had tried this without success but it is working now.
{% if template == 'product' %}
<title>{{ page_title }}</title>
{% else %}
<title>{{ page_title }}{% if current_tags %}{% assign meta_tags = current_tags | join: ', ' %} – {{ 'general.meta.tags' | t: tags: meta_tags }}{% endif %}{% if current_page != 1 %} – {{ 'general.meta.page' | t: page: current_page }}{% endif %}{% unless page_title contains shop.name %}{% if template != 'article' %} – {{ shop.name }}{% endif %}{% endunless %}</title>
{% endif %}