list.product_reference.size
I have a custom metafield of a product list. When I display the list {{ product.metafields.custom.mylist }} ["gid://shopify/Product/7668926775542","gid://shopify/Product/7491343778038"]
but {{ product.metafields.custom.mylist.size }} shows nothing
is list !== array?
We are having the same issue. Plus, giving the array to the Size filter always returns 0, whether the size is 0 or not
Having the same problem, can iterate over the array but size returns nothing.
If the product reference list metafield has never been used, i can check if it's nil: {% if product.metafields.custom.mylist == nil %}
But if the metafield has been used, but the data was removed, it isn't nil. The value console logs as []. But {% if product.metafields.custom.mylist.value.size > 0 %} doesn't work. This makes it impossible to check if there is data entered in the metafield.
I've been unable to find a workaround for this.
Is it that the "list" is only the storage of the data but the metafield is only storing string? maybe it only works with JSON.parse( product.metafields.custom.mylist)?
This worked for me:
{%- assign product_list = product.metafields.custom.mylist | split: ',' | uniq -%} {{ product_list.size }}
Still running into this issue as well but with collection lists (metafield type list.collection_reference). This issue was confirmed by Shopify support staff. Hoping this gets some attention from the maintainers soon.
upon till today this is still an issue, i.e. metafields of type list is not an array either has a size method.
Following works for now, i.e. manually converting it into an array of strings, then use its size.
{% assign productIngredients = product.metafields.custom.ingredient_details.value %}
{% assign productIngredientsArray = product.metafields.custom.ingredient_details | split: ',' %} // might want the uniq filter too
{% assign productIngredientsTotal = productIngredientsArray.size %}
Using .count instead of .size solves this issue for me.
Using
.countinstead of.sizesolves this issue for me.
Interesting, It seems ProductListDrop is not a type of array.
@annatwp solution worked for me
This trick might work to get the size, but this prevents to access an object such as a product reference. I described the issue here: https://github.com/Shopify/liquid/issues/1643#issuecomment-1410660908 I really wonder why this is not fixed yet, very annoying that we can have list but can't navigate them with liquid array filters.
Same here! Omg I'm going crazy with this issue.
Size isn't working either as a filter or using [dot]notation. It acts as if it doesn't have any item. Can't use conditional logic, can't loop over it, it's just like it's not an array...
But on the other hand when it gets JSON stringified it shows as an array on the console.
Here's some of the debugging I did:
Hopefully this gets solved fast!
@masserra use .value so artists.size.value
@masserra use .value so artists.size.value
I had tried {{ artists.value | size }} before, but it didn't work either.
Don't understand the why of using size.value, although I just tried it ({% if artists.size.value > 1 %}) and it didn't work either. Also this would not solve the for loop as it needs to be able to read the array as an array and until that happens size or anything else won't work.
This worked for me:
{%- assign product_list = product.metafields.custom.mylist | split: ',' | uniq -%} {{ product_list.size }}
upon till today this is still an issue, i.e. metafields of type
listis not an array either has asizemethod. Following works for now, i.e. manually converting it into an array of strings, then use its size.{% assign productIngredients = product.metafields.custom.ingredient_details.value %} {% assign productIngredientsArray = product.metafields.custom.ingredient_details | split: ',' %} // might want the uniq filter too {% assign productIngredientsTotal = productIngredientsArray.size %}
This is the only thing that worked for me to be able to use size..
BUT... then all I get is an array of metaobject GID reference strings ("gid://shopify/Metaobject/2167308566") which I can't find a way to access!
So... even though this was obviously a hack, this is definitely not the solution.
Solution:
OK!! Finally found the cleanest hack to make the array behave like an actual array, a double reverse filter:
{% assign metaobjects = metafields.namespace.key.value | reverse | reverse %}
To come back to my real world example would look like:
{% assign artists = metafields.custom.artists.value | reverse | reverse %}
Key points that need to be reviewed:
- The use of
valueis completely unintuitive. When logging the JSON stringified object/array there's nothing there to suggest the use ofvalue. On top of that it's poorly documented if not completely undocumented. - Using
valueon its own doesn't even take you anywhere. The returned array won't work with the Shopify liquid standards such assizefilter orforloops. You won't get an array of actual type array until we apply hacks such as the doublereversefilter. - Due to the very unintuitive nature of
valuein conjunction with the array not behaving as expected we find ourselves completely lost throwingvalueeverywhere until we realize it's a liquid bug.
Note to the Shopify Liquid Team:
It's almost been 1 year since this issue has been opened, everywhere I look I see people struggling not only with the use of value but also with the fact that "list !== array" as @chucklin72 suggested. It's very confusing and it's clearly a liquid bug since double reverse filter finally turns the list into the expected array type.
The longer this goes on unsolved the more codebases might end up having a breaking change once you finally tackle the issue..
I can't believe your solution is actually working!! Great finding @masserra You nailed it.
So something like this is now possible:
{% assign my_product = product.metafields.custom.product_list.value | reverse | reverse %}
Product title: {{ my_product[1].title }}
A standard for loop works normally as well, but in some situations it is not a practical way to code:
{% for value in product.metafields.custom.product_list.value %}
Product title: {{ value.title }}
{% endfor %}
I can't agree more with you with the issues you highlighted. Shopify simply ignores us here, I don't mean to be rude or offensive, but why did they not address this at least once, it is puzzling...
As for the metafields value, I belive this is the doc for liquid. I must say this is quite a gymnastic for the mind (especially metaobjects), not always easy to get it right the first time, but I suppose they've had a good reason to do it, and the changes they did to metafields are overall very good.
Now, I wonder if this "trick" is a good idea for production. Could it not backfire? As long as there is no breaking change introduced (which is something I've never seen Shopify do yet), I don't mind using this trick, this can make code simpler and cleaner.
@MaxDesignFR 🙌 🙌 Thank you for that liquid doc, it completely escaped me. Although, what I also mean by "unintuitive" is that JSON stringifying the object doesn't expose the correct tree structure, it suggests that the list can be accessed straight away and that no other attribute (value) needs to be used to access the list 1 more step down the tree.
I spoke to a Shopify admin on discord and they said it's all about priorities as they have many other higher important issues to tackle, which I understand actually, they've indeed been pushing quite a lot of new exciting features lately 🫶
In regards to being production ready I don't see why it might not be. I'll choose this one over any other solution (for now) as this one at least is a clean & explicit hack that feels familiar to other devs and doesn't go around the problem too much, a simple comment and every dev will be in sync. Plus it enables us to use only Shopify's documented liquid standards and no undocumented ones such as .count.
If size is 0 then I try count. Seems to be working for me.
We have a metaobject that has a field that accepts products (list) and this is how I solved the counting issue:
assign gift_count = promo.product | split: ',' | size
{{ metafields.custom.array.value.count }} worked for me, God knows why.