shopifyliquid

How to fetch products data using product handle from an array containing handles in shopify


I've a list of product handles stored in the main products metafield that I'm fetching in the following way:

{% assign firstComponentHandles = product.variants.first.metafields.custom.component_handles %}

const handlesData = {{ firstComponentHandles }};
console.log({handlesData}); 

Response:

{
    "handlesData": [
        "burger",
        "carbonated-beverage"
    ]
}

Now I've taken multiple approach to fetch the products data using the handles. I've used the all_products liquid obj for fetching the data using the handles:

Using js:

<script>
  {% assign firstComponentHandles = product.variants.first.metafields.custom.component_handles %}  

  const handlesData = {{ firstComponentHandles }};
  console.log({handlesData});

  const componentsData = [];

  handlesData.forEach((componentHandle, index) => {

    componentsData.push({ componentHandle: {{ all_products.componentHandle | json }} });

    componentsData.push({ componentHandle: {{ all_products[componentHandle] }} });

  });

  console.log("Components Data:", componentsData);
</script>

Response:

Uncaught ReferenceError: EmptyDrop is not defined

Inspection on sources:

    handlesData.forEach((componentHandle, index) => {

    componentsData.push({ componentHandle: {"error":"json not allowed for this object"} });

    componentsData.push({ componentHandle: EmptyDrop });

  });

Using Liquid:

<script>

  const componentsDataNew = [];
  const componentsDataNew2 = [];

  {% for handle in firstComponentHandles %}

    componentsDataNew.push({handle: {{ all_products.handle | json }}})
    componentsDataNew2.push({handle: {{ all_products[handle] | json }} });

  {% endfor %}

  console.log("Components Data Array New: ", componentsDataNew);
  console.log("Components Data Array New 2: ", componentsDataNew2);

</script>

Response:

Components Data Array New:  []
Components Data Array New 2:  []

Passing static handle:

<script>
  const dataUsingStatichandle = [];

  dataUsingStatichandle.push({ burger: {{ all_products.burger }} });
  dataUsingStatichandle.push({ burger2: {{ all_products["burger"] }} });
</script>

Response:

[
    { "burger": { "id": 8654927343434, "title": "Burger", ...moreData } },
    { "burger2": { "id": 8654905131564, "title": "Burger", ...moreData } }
]

So, I couldn't fetch the data using either Js or Liquid dynamically but I could fetch them passing the handle statically.

What am I doing wrong? I feel like this should be a syntax related issue.


Solution

  • I figured it out. The main problem was with the data format and it was a hectic process. It took me quite some time to figure out what was wrong.

    1st problem that I found was that the liquid loop wasn't working with the data I was passing. I was getting the handles data as an array:

    [
       "burger",
       "carbonated-beverage"
    ]
    

    So then I assigned it to a Liquid variable and then I removed the '[' and then removed the ']'. After removing the parenthesis I removed the '"' double quotes. Then I split the result using ',' and then the handles were ready to use in a liquid loop.

    The liquid code:

    <script>
    
      {% assign firstComponentHandles = product.variants.first.metafields.custom.component_handles %}  
      {{ firstComponentHandles }}
      // Output: ["burger","carbonated-beverage"]
    
      {% assign temp1 = firstComponentHandles | remove: '[' %}  
      temp1: {{ temp1 }}
      // Output: temp1: "burger","carbonated-beverage"]
    
      {% assign temp2 = temp1 | remove: ']' %}  
      temp2: {{ temp2 }}
      // Output: temp2: "burger","carbonated-beverage"
    
      {% assign temp3 = temp2 | remove: '"' %}  
      temp3: {{ temp3 }}
      // Output: temp3: burger,carbonated-beverage
    
      {% assign formattedHandles = temp3 | split: ',' %}  
      {{ formattedHandles }}
      // Output: burgercarbonated-beverage
    
      const productsWithVariantsQty = {};
    
      {% for handle in formattedHandles %}
    
        {% assign productFromHandle = all_products[handle] %}
    
        // Initialize the key for each product handle and set it as an empty array
        productsWithVariantsQty["{{ handle }}"] = [];
    
        {% for variant in productFromHandle.variants %}
    
          productsWithVariantsQty["{{ handle }}"].push({
            variantInventoryQuantity: {{ variant.inventory_quantity }},
            variantInventoryPolicy: "{{ variant.inventory_policy }}"
          });
    
        {% endfor %}
    
      {% endfor %}
    
      console.log("Products with Variants:", productsWithVariantsQty);
    
    </script>