Have your say in Community Polls: What was/is your greatest motivation to start your own business?

Loop through products in a variable-defined collection

Loop through products in a variable-defined collection

whecka
Shopify Partner
1 0 0

This is an evolution of the question asked at https://community.shopify.com/c/technical-q-a/looping-through-products-from-a-particular-collection/....

 

I have a lot of products sorted into multiple collections each. For my product pages, I'm trying to create a "Pairs Well With" section that shows products from the current product's "parent" collection. I've got code to loop through the current product's various collections and produce only the collection with the fewest products in it (the nearest "parent" collection) as the value for a variable.

 

But when I try to use that resulting variable in the definition for a forloop, nothing comes out, regardless of syntax. Is there a way to include a variable x in a forloop, like {% for product in collection[x].products %}?

or

Is there a better way to surface a product's parent collection and pull content only from it?

 

 

{%- capture j -%}
  {%- for collection in product.collections -%}
      {{ collection.all_products_count }}{{ collection.handle }}
      {%- if forloop.last == false -%}::{%- endif -%}
  {%- endfor -%}
{%- endcapture -%}

{%- assign jarray = j | split: "::" | sort | reverse -%}
{%- assign k = jarray[1] | remove: "1" | remove: "2" | remove: "3" | remove: "4" | remove: "5" | remove: "6" | remove: "7" | remove: "8" | remove: "9" | remove: "0" | prepend: "'" | append: "'" | strip | strip_newlines -%}
{%- assign current = product.url -%}

<div class="reco">
  <div class="reco-header">Pairs Well With</div>
  <div>
    <ul class="reco-options">
      {% for product in collections['recommendations'].products limit:3 %}
        {% if product.url != current %}
          <li class="reco-option">
            <a href={{ product.url }}>
              <img class="reco-image" src="{{ product.featured_image | img_url: '1000x'}}">
              <div class="reco-name__box">
                <h3 class="reco-name">{{ product.title }}</h3>
              </div>
              <h4 class="reco-price">{% unless product.tags contains 'fullprice' %}{{ product.compare_at_price | money }}{% else %}{{ product.price | money }}{% endunless %}</h4>
              <btn href="{{ product.url }}" class="reco-add">View</btn>  
            </a>
          </li>
        {% else %}
          {% continue %}
        {% endif %}
      {% endfor %}
    </ul>
  </div>
</div>

 

 

Replies 2 (2)

ri31
Shopify Partner
7 0 2

In case this is helpful to someone, I will reply even though it's a while later.

 

It looks like you are using "recommendations" as at the name of a variable, but you don't have a definition for that variable. You need to define it first using "assign".

 

In your formatting, do not use any quotation marks around the name of the variable. Try just put it in the string where you are referencing the object namespace and field key without any extra marks around it. You can use dots or square brackets. Like this: 

{% for product in collections.recommendations.products limit:3 %}

or

{% for product in collections[recommendations].products limit:3 %}

 

In my testing, I found that 

  • using square brackets around a variable name does NOT work
  • using dots . around a variable name DOES work.
  • Using 2 variables in 1 reference string does NOT work -- at least, I have not found a way yet.

 

Here is what I have tested.

NOTE: This is what the liquid code is returning on the live page. This isn't the liquid code itself. For each step, I have a description of what the code is doing in bolded text, followed by the result of the test in regular weight font.

 

assign repeated_object = shop.metaobjects.bike_guide

 

Check that the variable is assigned correctly. Value of repeated_object:
MetaobjectDefinitionDrop

Test appending additional strings to a variable to pull data from an object

Check hard-coded string without using variables. SUCCESS.
Value of shop.metaobjects.bike_guide.values_count: 10

 

Test using variable in square brackets. FAIL.
Value of [repeated_object].values_count:

 

Test using variable without square brackets. SUCCESS.
Value of repeated_object.values_count: 10

Test combining 2 variable strings using append filter

This doesn't work. It seems the value of the variable is first being pulled, then it's having the extra string appended, instead of just appending it to the name of the variable. I need to find a way to get the value of the variable as a string, without actually loading the value of the object that that string represents.

 

Test creating a longer string from the first variable. assign appended_object = repeated_object | append: ".values_count"

 

Value of appended_object. It's not combining the 2 strings, it's instead adding a string on to the value of the first variable:
MetaobjectDefinitionDrop.values_count

Test combining 2 variable strings by placing them one after the other

This doesn't work but I don't know why not.

assign field_variable = "values_count"

 

Value of field_variable:
values_count

 

Value of repeated_object.field_variable. FAIL (does not return anything).

 

Value of [repeated_object][field_variable]. FAIL (does not return anything).

 

ri31
Shopify Partner
7 0 2

Since I can't edit the previous reply, replying again.

 

I was now able to get multiple variables to work together to load a value in liquid. I think part of the secret is that none of these variables, by itself, represents any Liquid object in my store.

 

Here is the exact code and the first result.

 

CODE:

{%- assign key_part_1 = 'brand' -%}
{%- assign key_part_2 = 'value' -%}
{%- assign key_part_3 = 'brand' -%}
{%- assign multi_level_key = 'brand.value.brand' -%}
{%- assign repeater_filter = 'Cipollini' -%}
{%- assign repeated_object = 'bike_guide' -%}

<h2>Variable Data</h2>
<p>key_part_1: {{key_part_1}}</p>
<p>key_part_2: {{key_part_2}}</p>
<p>key_part_3: {{key_part_3}}</p>
<p>repeater_filter: {{repeater_filter}}</p>
<p>repeated_object: {{repeated_object}}</p>

<h2>Testing the variables inside a for loop</h2>
{%- for item in shop.metaobjects[repeated_object].values -%}

<h3>Test using one variable</h3>
<p><b>item.brand:</b> {{item.brand}}</p>

<p><b>item[key_part_1]:</b> {{item[key_part_1]}}</p>

<p><b>item.key_part_1:</b> {{item.key_part_1}}</p>

<h3>Test using 2 variables</h3>
<p><b>item.brand.value:</b> {{item.brand.value}}</p>

<p><b>item[key_part_1][key_part_2]:</b> {{item[key_part_1][key_part_2]}}</p>

<h3>Test using 3 variables</h3>
<p><b>item.brand.value.brand:</b> {{item.brand.value.brand}}</p>

<p>item[key_part_1][key_part_2][key_part_3]: {{item[key_part_1][key_part_2][key_part_3]}}</p>

{%- assign item_key = item[key_part_1][key_part_2][key_part_3] -%}
<p>The full item key is {{item_key}}</p>

{%- if item_key == repeater_filter -%}

<p style="color: green;"><b>This item passed the filter.</b></p>

{%- endif -%}
{%- endfor -%}

 

FIRST RESULT:

ri31_0-1732567661782.png

 

ri31_1-1732567682086.png