Shopify Liquid Tag within Asset Tag - shopify

I'm trying to insert a metafield variable within an asset url as below:
{% assign review = product.metafields.review %}
{% assign key = 'rating' %}
<img src="{{ '[review.rating].png' | asset_url }}"/>
For some reason it isn't returning the actual variable, instead the text itself, is there a way to go about doing this?

If any reviews actually exist at the namespace product.metafields.review then you have to iterate through them. When you do that, for each iteration you'll get some key value pairs. With those you can print out the actual data of the metafield resources. What you are attempting there in your snippet seems a bit off. Try accessing the rating key in your iterator, and if it exists, the value would be available to you for your image snippet.

Related

How to work with product meta field in Shopify?

I have created a custom meta field for blog posts in Shopify. It's of the type product and I have chosen List of products.
I want to loop through the products and render them using the theme's product-grid-item template.
My problem is, that the type of my meta field output is a string - not an array.
If i try to output the field like this {{ article.metafields.blog_post.feature_products }}
I get the following:
["gid://shopify/Product/8078688583991","gid://shopify/Product/8078688715063","gid://shopify/Product/8078689141047"]
Which looks like an array, but liquid sees it as a string.
I have tried to loop through it like the following. But nothing happens
{% for product_id in article.metafields.blog_post.feature_products %}
{{ product_id }}
{% endfor %}
It feels like I'm missing something obvious. It doesn't make sense, that the output is a string.
Does anybody know how to output it like an array? Or how to convert the string to an array - without the quote-marks, brackets and so on.
For metafields that allow multiple values, the list of values is stored in the value property of the metafield. Add .value at the end of your loop statement.
Note that your product_id variable will be a product object. I suggest you rename it to "product". You can then access the id (and other properties) using the dot notation.
{% for product in article.metafields.blog_post.feature_products.value %}
{{ product.id }}
{% endfor %}

Cycle inside render tag

I am looping through products and I need the cycle tag based on loop.
{% for product in collection.products %}
{% render 'product-grid-item', product: product %}
{% endfor %}
Inside the "product-grid-item", I have:
{% assign class_1 = 'small-6 medium-4' %}
{% assign class_2 = 'small-6 medium-3' %}
{% capture grid_item_width %}
{% cycle class_1, class_1, class_1, class_2, class_2, class_2, class_2 %}
{% endcapture %}
The cycle is not working, because it is not directly inside the "for loop". Any idea how to get this working?
I am aware of alternatives, I am just trying to make "cycle" work inside a render tag.
Render is a closed piece of code, it can't read what is happening outside of it.
So at the moment you not only don't have access to the cycle but you don't have access to the forloop object as well.
You are looking for how the include works but that is deprecated and you shouldn't use it.
So the short answer is you can't make it work, since the main logic of the render is to work this way.
The only way to make the render aware of something outside it is to pass a variable to it, so you need to make your cycle logic outside of it and pass the resulting variable inside of it.
What you are trying to do is possible as long as you rearrange your approach slightly. You will just need to do your math outside of the snippet and pass an appropriate value as a variable into the snippet.
{% assign class_array = 'class-1,class-1,class-1,class-2,class-2,class-2,class-2' | split: ',' %}
{% for product in collection.products %}
{% assign loop_position = forloop.index0 | modulo: class_array.size %}
{% render 'product-grid-item', product: product, class_name: class_array[loop_position] %}
{% endfor %}
How this works
Just like before, we make a comma-separated array of class names that we want to cycle through. (We cannot make an array directly, but we can turn a delimited string into an array pretty easily using the split filter) - but this time we assign that to a variable.
We then use the forloop index and the modulo operator to get a value between 0 and the last index position of our array list and use that number as the lookup value for our array. That value is passed into the rendered snippet so that product-grid-item can access it.
If we ever need to change our cycling class names, all we have to do is update the array with the new values. Even if the number of values changes in the future, the code will still work to cycle through all of the values provided.
Cheers!

How to access variable from the variable

I have added a Metafields Guru app in my shopify store. I have created some metafields there And I want them to access in my template. All these are easily accessible if I access them individually. But problem is that how could I access if the key field come from another variable. I want code snippet something like below one.
{{product.metafields.productmeta.{block.settings.patitle | downcase }}}
block.settings.patitle comes from section block in a loop. And same downcased title is used as an key in metafields.
You can capture that string as something like a key:
{% capture mykey %}{{ block.settings.patitle | downcase }}{% endcapture %}
Then you can try accessing your metafield with that variable as in:
{{ product.metafields.productmeta.mykey }}
If that does not work, then why not try the string interpelation:
{{ product.metafields.productmeta['{{block.settings.patitle | downcase }}'] }}
Enough experimenting should get you what you want.

Displaying the current collection on a product info page (shopify liquid)

I am on the product info page and would like to know if its possible to get the current collection that the product is in so that i can do some stuff. How can i get the current collection? I have tried collection.title and it doesnt show anything.
In order to get the CURRENT collection, you MUST have the collection handle in your URL.
So for example if the product URL is something like so /collections/COLLECTION_HANDLE/products/PRODUCT_HANDLE you will have access to the current collection.
In your case since you don't have access to the collection title I assume that your URL is just /products/PRODUCT_HANDLE.
This means that you are generating the wrong URL's ( not wrong, but not full ). You must look for product.url in your collection and add the filter within: collection.
So your collection liquid code should look something like this
{% for product in collection.products %}
... SOME OUTPUT ...
Details
{% endfor %}
This will force your product url to include the collection URL as well.
Try it if your URL in this format "/collections/COLLECTION_HANDLE/products/PRODUCT_HANDLE"
Try This:
This product is in the {{ collection.title }} Collection.
Although there might be many collections product assigned but the better way to get the current collection title that is in URL
Note: Using this code you can do stuff on your product page only if collection is in the URL.
{% assign product_collection = collection.title | link_to: product_collection.url %}
{% unless product_collection == blank %}
<h3>Current Collection is: {{ product_collection }}</h3>
{% endunless %}

Jinja / Django for loop range not working

I'm building a django template to duplicate images based on an argument passed from the view; the template then uses Jinja2 in a for loop to duplicate the image.
BUT, I can only get this to work by passing a list I make in the view. If I try to use the jinja range, I get an error ("Could not parse the remainder: ...").
Reading this link, I swear I'm using the right syntax.
template
{% for i in range(variable) %}
<img src=...>
{% endfor %}
I checked the variable I was passing in; it's type int. Heck, I even tried to get rid of the variable (for testing) and tried using a hard-coded number:
{% for i in range(5) %}
<img src=...>
{% endfor %}
I get the following error:
Could not parse the remainder: '(5)' from 'range(5)'
If I pass to the template a list in the arguments dictionary (and use the list in place of the range statement), it works; the image is repeated however many times I want.
What am I missing? The docs on Jinja (for loop and range) and the previous link all tell me that this should work with range and a variable.
Soooo.... based on Franndy's comment that this isn't automatically supported by Django, and following their link, which leads to this link, I found how to write your own filter.
Inside views.py:
from django.template.defaulttags import register
#register.filter
def get_range(value):
return range(value)
Then, inside template:
{% for i in variable|get_range %}
<img src=...>
{% endfor %}