Using a string to create a Liquid variable - shopify

In my shopify store, I am using SuperFields in order to customize my site, though my question isn't about the app. On one of my pages, I need the value for the following:
variant.metafields.sf_{{ collection.title | downcase }}[meta_tag_key]
The value should be 0 or 1. If I evaluate the statement directly, such as:
{if variant.metafields.sf_{{ collection.title | downcase }}[meta_tag_key] =1%}
It throws an error when I render the page: Unexpected character '{'
I've also tried the following:
{% capture defaultImage %}variant.metafields.sf_{{ collection.title | downcase }}[meta_tag_key]{% endcapture %}
{% assign test = defaultImage %}
But 'test' is considered nil and doesn't return any value. I have tried to search for answers here and on the shopify forum, but, as my clumsy post title suggests, I'm having a hard time concisely searching for a solution to this problem. Any help is greatly appreciated.

You can try :
{% assign metafield-key = collection.title | downcase | prepend: "sf_" %}
{% assign key = variant.metafields[metafield-key][meta_tag_key] %}
{% if key == 1 %}
Do the twist !
{% endif %}

You are missing a % sign in your code. Hence the error message. Your if statement started with {% and not just {

If you working in liquid then you have to use {% %} for defining any variable & also for condition in shopify. You can't use { this.

Related

Liquid coding (Shopify) "and" and "elsif" not functioning together

I'm new to liquid coding while starting my own Shopify store (although I had some experience with coding). I'm currently stuck trying to get this code to function. I've added 3 text options in the liquid file for each variable. The idea is that when the criteria are met, it would display the appropriate text option. Please see the code string here for ref.
{% if section.settings.free_shipping_announcement_bar %}
{% assign promote_text = section.settings.promote_free_shipping_text | escape %}
{% assign unlocked_text = section.settings.unlocked_free_shipping_text | escape %}
{% assign unlocked_del_text = section.settings.unlocked_free_delivery_text | escape %}
{% assign threshold = section.settings.free_shipping_threshold | times: 100 %}
{% assign value_left = threshold | minus:cart.total_price %}
{% assign value_left_money = value_left | money %}
<div class="announcement-bar">
{% if value_left <= 0 %}
<p class="announcement-bar__message">{{unlocked_text}}</p>
{% elsif value_left >= 1 and value_left < 50 %}
<p class="announcement-bar__message">{{unlocked_del_text}}</p>
{% else %}
<p class="announcement-bar__message">{{promote_text | replace:'(value)' , value_left_money}}</p>
{% endif %}
basically, the idea is if the cart total is between $0-$99 I will show the "promote_text", if it's between $100-$149 it will show the "Unlocked_free_del_text"(free delivery), then at $150+ in the cart it shows "unlocked_text".
It currently shows the "promote_text" from $0-$149 then changes directly to the "unlocked_text" and skips the middle section for "unlocked_del_text"
my best assumption is that I'm using the elsif function wrong but I've trailed as many adjustments as I can think of without breaking the code, so any advice would be greatly appreciated!
Update:
After checking and testing the code over dev store I find you need to use divided_by to value_left value to compare with the value into normalized format.
so your code needs an update to this line
{% assign value_left = threshold | minus:cart.total_price | divided_by: 100%}
becase case is multile of 100 to process to cart value and need to normalized before test into if else condition.
The code looks great, I am not sure why this not works properly, you can check and try in this way also and I hope it will work. overwise you need to post the whole code along with schema and anyone replicate it dev store and find the solution.
{% if section.settings.free_shipping_announcement_bar %}
{% assign promote_text = section.settings.promote_free_shipping_text | escape %}
{% assign unlocked_text = section.settings.unlocked_free_shipping_text | escape %}
{% assign unlocked_del_text = section.settings.unlocked_free_delivery_text | escape %}
{% assign threshold = section.settings.free_shipping_threshold | times: 100 %}
{% assign value_left = threshold | minus:cart.total_price | divided_by: 100%}
{% assign value_left_money = value_left | money %}
<div class="announcement-bar">
{% if value_left <= 0 %}
<p class="announcement-bar__message">{{unlocked_text}}</p>
{% elsif value_left >= 1 and value_left < 50 %}
<p class="announcement-bar__message">{{unlocked_del_text}}</p>
{% else %}
<p class="announcement-bar__message">{{promote_text | replace:'(value)' , value_left_money}}</p>
{% endif %}
</div>
{% endif %}
Thanks for the quick response! I trialed the snippet you added but unfortunately ran into the same issue. here is the schema that I added to impact the section of code I input. If you are able to spot a simple issue in here please let me know, otherwise, I will continue to troubleshoot personally and hopefully find a solution or alternate method, to avoid troubling someone with having to replicate the entire code to recreate the issue.
{
"type":"checkbox",
"label":"enable free shipping bar",
"id":"free_shipping_announcement_bar",
"default":false
},
{
"type":"text",
"id":"promote_free_shipping_text",
"label":"message to promote free shipping"
},
{
"type":"text",
"id":"unlocked_free_shipping_text",
"label":"message for unlocked free shipping"
},
{
"type":"text",
"id":"unlocked_free_delivery_text",
"label":"message for unlocked free delivery"
},
{
"type":"range",
"id":"free_shipping_threshold",
"label":"threshold for free shipping",
"min":0,
"max":200,
"step":5,
"unit":"$",
"default":150
}

Shopify Liquid get every even block in forloop

i am trying to get every block that has an even position in shopify liquid inside a forloop :
{% for block in section.blocks %}
{% if forloop.index | modulo : 2 == 0%}
//some code
{%endif%}
{% endfor %}
but shopify returns me this error:
Expected end_of_string but found pipe in "forloop.index | modulo : 2
== 0"
Can somone help me solve this?
Thanks in advance :D
You need to split calculations from logic in liquid.
{% assign num = forloop.index | modulo: 2 %}
{% if num == 0 %}
// code
{% endif %}
So you must save the module calculation as variable and check it after that, you can't do the check and calculation at the same time.

Passing previously assigned variable in `{% for` block in Shopify

In blog-templte.liquid
{% assign articleSortOrder = '' %}
....
{% for article in blog.articles {{articleSortOrder}} %}
got an error : Liquid syntax error: Unexpected character { in "article in blog.articles {{articleSortOrder}}"
The intention is to pass the variable to sort the articles depending on some condition.
Q: is how to make it work?
This is not a valid liquid code:
{% for article in blog.articles {{articleSortOrder}} %}
You can't pass a liquid inside a liquid, a.k.a {% {{ }} %}
In addition for loops accept only a few parameters:
reversed - which will reverse the loop
limit - which will limit the iterations
offset - which will make the loop skip a specific set number of items
Sort is not one of them.
You can read more about the for loop here: https://shopify.dev/docs/liquid/reference/tags/iteration-tags
In order to sort the blog in a specific way you must code it like so:
{% assign articleSortOrder = '' %}
{% assign blog_articles_sort = blog.articles | sort: articleSortOrder %}
{% for article in blog_articles_sort %}
{% endfor %}
Where you assign the articles in a specific variable and sort them.
Please have in mind that this will sort ONLY 50 articles.
If you like to sort more than 50 you will need to overwrite the paginate object {% paginate blog.articles by 9999 %}
Then your code will look like this:
{% paginate blog.articles by 9999 %}
{% assign articleSortOrder = '' %}
{% assign blog_articles_sort = blog.articles | sort: articleSortOrder %}
{% for article in blog_articles_sort %}
{% endfor %}
{% endpaginate %}
More about paginate can be seen here: https://shopify.dev/docs/liquid/reference/tags/theme-tags/#paginate
Please have in mind that the sort function in Shopify is limited. You may need to sort them with javascript or another approach depending one what you are looking for.

How to use a variable as a key in a hash in liquid (Shopify)

I would like to set up a hash variable using strings from an array dynamically (instead of writing 1000 lines of code).
As well I would like to use a dynamically created string to access a hash by using it as the key - for a built-in (what I assume is a hash) object - settings. Settings allow you to access data in settings_schema.json, eg: settings.my_custom_setting
According to this documentation: https://github.com/Shopify/liquid/wiki/Liquid-for-Designers
"For hashes, the key must be a literal quoted string or an expression that resolves to a string."
so I have tried {% assign filter[thisFilter] = false %} but get an error: ParseError: illegal token
First issue / accessing hash key with a variable:
{% comment %} All possible filters {% endcomment %}
{% assign allFilters = "color,size,collection,style,height,function,artist" %}
{% assign allFiltersArray = allFilters | split ',' %}
{% comment %} hash of filters each set to false {% endcomment %}
{% for thisFilter in allFiltersArray %}
{% assign filter[thisFilter] = false %}
{% endfor %}
Second issue, accessing settings object with a dynamically generated key:
{% comment %} set to true whichever filters are configured in settings for this collection {% endcomment %}
{% for thisCollection in allCollectionsArray %}
{% if thisCollection == currentCollection %}
{% for thisFilter in allFiltersArray %}
{% assign itemToCheck = "filter_" | append: thisCollection | append: "_" | append: thisFilter %}
{% if settings[itemToCheck] %}
{% assign filter[thisFilter] = true %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
In the first issue, I expect the result to be a hash such as:
filter['color'] = false (or filter.color = false)?
filter['size'] = false
In the second issue, I'm expecting something like:
{% if settings.filter_shirts_color %}
What you are trying to do is not possible. If you read further on your provided link Liquid for Designers, it is mentioned
Note that there is no way to write a literal array or hash as an
expression; arrays and hashes must be passed into the template, or
constructed obliquely with a tag or output statement.
Moreover, even if you have such hash, you cannot assign it new value. For example,
{% assign settings['some-setting-id'] = false %}
This will not work. Same is the case with array created using split filter. You cannot assign new values on any index.
For the second issue, this should work, the error in your case most probably is because of invalid generated string or there is no setting with that id. This should work fine and display value for that setting.
{%assign string_key = 'setting-key'%}
{{settings[string_key]}}
But this will not work because
{%assign string_key = 'setting-key'%}
{{settings.string_key}}
my_hash.key — Hashes also allow a shorter "dot" notation, where the
name of the variable is followed by a period and the name of a key.
This only works with keys that don't contain spaces, and (unlike the
square bracket notation) does not allow the use of a key name stored
in a variable.

Liquid - Convert Array to Lowercase

I'm using Shopify and want to hook into customer tags, however they are case sensitive. So {% if customer.tags contains "wholesale" %} is not the same as {% if customer.tags contains "Wholesale" %}. My client may or may not stick to one case when applying tags so I want to guard against that in the future.
I would like to take an array, customer.tags, and convert all of the values to lowercase. I'm trying to work out the logic but am having trouble.
I want to put customer.tags into a new array which isn't working.
{% assign newArray = customer.tags %}
{{ newArray }}
What am I doing wrong?
You could use the downcase filter for this:
{% assign contains_wholesale = false %}
{% for tag in customer.tags %}
{% assign lowercase_tag = tag | downcase %}
{% if lowercase_tag == 'wholesale' %}
{% assign contains_wholesale = true %}
{% endif %}
{% endfor %}
Note: downcase just works for ASCII characters. If you need to search for strings with accented letters or other Unicode characters then this won't be enough.
if you would like to keep customer.tags as an array so you can keep using contains in a simple if statement (like your example). You could also chain a couple of liquid filters together to turn all of the strings within the array to lowercase.
Example:
{% assign lowercaseTags = customer.tags | join: ',' | downcase | split: ',' %}
{% assign randomString = 'WholeSale' | downcase %}
{% if lowerCaseTags contains randomString %}
{% comment %}
Will now match regardless of case sensitivity
{% endcomment %}
{% endif %
Explanation:
Join filter: Turn the array into a string seperated by ,
Downcase filter: make the whole string lowercase
Split filter: opposite of join, recreates the array from the string based on the character used in join ,
Another solution as you use the "contains" operator would be to skip the "w".
Something like {% if customer.tags contains 'holesale' %} should work.