Variable storing metafield path being rendered as string

Hello there, everyone!

I’m trying to create a loop to generate ‘rows’ for a table using metafields for each of the data points. I know there’s a tablerow loop in Liquid, however it won’t work well with the current codebase since we’re not able to use HTML tables due to very specific technical limitations.

That being the case, I’m trying to generate rows as divs dynamically using the forloop index as a variable on the metafields themselves, because the only thing that changes on the metafield handle for each datapoint is the number as you can see in the code below. That way the logic can be written once instead of having to do it in a super repetitive way (and also not dynamic).

The issue is that when the page is rendered, instead of rendering the value of the metafields themselves, it’s rendering the metafield path as a string directly to the front end:

Here’s my current code:

{% assign rowLimit = product.metafields.global.row-count %}
          {% for i in (1..rowLimit) %}        
              {% capture tableLength %}
              product.metafields.global.table-length-{{ i }}
              {% endcapture %}
              {% capture tableWidth %}
              product.metafields.global.table-width-{{ i }}
              {% endcapture %}
              {% capture tableThickness %}
              product.metafields.global.table-thickness-{{ i }}
              {% endcapture %}
              {% capture tableVolume %}
              product.metafields.global.table-volume-{{ i }}
              {% endcapture %}

              {% if  tableLength %}
                  
                    
{{ tableLength }}

                    {{ tableWidth }}

                    {{ tableThickness }}

                    {{ tableVolume }}

                  

              {% endif %}
          {% endfor %}

I believe the liquid variable is being processed and returning the variable’s value as a string which is then the output to the browser. How can I process the value of the variable and then use it inside {{ }} for example to process the actual metafield path instead of a string?

I would really appreciate it if you would help me figure this out!

Thanks in advance and have a great day!

Not tested but it should work:

{% assign key = 'table-thickness-' | append:  i %}
{{ product.metafields.global[key] }}
1 Like

Hello there, @Mircea_Piturca !

Thank you soooo much for your prompt reply : )
Your solution worked perfectly, I iddn’t know I could encapsulate the variable that way!

The only thing I had to add was a dot after global to make this work perfectly!

Here’s how the resulting code turned out in case any one is wondering:

{% assign rowLimit = product.metafields.global.row-count %}
          {% for i in (1..rowLimit) %}        
              {% assign tableLength = 'table-length-' | append:i %}
              {% assign tableWidth = 'table-width-' | append:i %}
              {% assign tableThickness = 'table-thickness-' | append:i %}
              {% assign tableVolume = 'table-volume-' | append:i %}

			
            	
{{ product.metafields.global.[tableLength] }}

				{{ product.metafields.global.[tableWidth] }}

				{{ product.metafields.global.[tableThickness] }}

				{{ product.metafields.global.[tableVolume] }}

			

          {% endfor %}

Thanks a million once again, @Mircea_Piturca !

Have a great one : )

Yes, Liquid is cool like that!

You can access object’s properties by using the dot notation or the bracket notation. Same as in JS.

Happy to help out

Hi Fernando and Mircea,

I’m having a similar problem but this approach isn’t solving it for me. It’s either returning nothing or weird obj like {“11053187399853”=>“rx requested 2x”}. Would greatly appreciate any advice.

My problem: I want to store specialized line item fulfillment statuses that a user will see when viewing an order. (Client has a complicated flow for insurance and prescription verifications with like a dozen Salesforce statuses.) The LineItem object does not have metafields, so I want to store them in Orders using the line item ID as the metafield key.

The idea is that I can then programmatically update statuses via API and display them via Liquid. However, I’m having a devil of a time getting the liquid side to work.

An example metafield as seen in GraphiQL:

"metafields": [
        {
          "id": "gid://shopify/Metafield/20905653272749",
          "namespace": "sfc",
          "key": "11053187399853",
          "value": "RX Requested 2x",
          "createdAt": "2022-02-23T07:12:39Z",
          "updatedAt": "2022-02-23T07:12:39Z"
        }

In a loop of

{%- for line_item in order.line_items -%}

I tried your method, but it would not return a value. When I tried a few different workarounds, the best I’ve come up with gives me a strangely formatted string instead: {“11053187399853”=>“rx requested 2x”}

I have the following example tests:

{% capture line_txt %} 
  {{ line_item.id }}.value
 {% endcapture %}
 {% capture line_ind %}
  ['{{ line_item.id }}']
 {% endcapture %}
 {% assign lid = {{line_item.id}} %}
 {% assign no_frills = order.metafields.sfc.{{ line_item.id }}.value %}
 {% assign no_frills_ind = order.metafields.sfc['{{ line_item.id }}'] %}
 {% assign test_case = order.metafields.sfc.{{ line_txt }} %}
 {% assign test_ind = order.metafields.sfc{{ line_ind }}} %}

 

 

counter: 35

 

no frills: {{ no_frills }}

 

no frills ind: {{ no_frills_ind }}

 

test case: {{ test_case | capitalize}}

 

test index: {{ test_ind }}

 

indirect dot: {{ order.metafields.sfc.[line_txt] }}

 

lid dot: {{ order.metafields.sfc.[lid].value }}

 

indirect ind: {{ order.metafields.sfc[line_ind] }}

 

direct: {{ order.metafields.sfc.11053187399853.value }} 

 

direct ind: {{order.metafields.sfc['11053187399853'] }}

 

test is still json: {{ test_case['11053187399853'] }}

Which give me these results:



counter: 35



no frills: {“11053187399853”=>“RX Requested 2x”}



no frills ind:



test case: {“11053187399853”=>“rx requested 2x”}



test index: {“11053187399853”=>“RX Requested 2x”}



indirect dot:



lid dot:



indirect ind:



direct: RX Requested 2x



direct ind: RX Requested 2x



test is still json: RX Requested 2x

If you’re able to give any guidance at all, I’d greatly appreciate it! I’ve been banging my head on the desk over this one.

For anyone else who has similar problem. The arrow function looking thing I’m pretty sure was Ruby hash rocket getting passed b/c of bad key.

Source of my problem was type. The key was an integer instead of string, and my attempts to convert to string were failing quietly. But not entirely, so I was getting hash rocket instead of the value.

Anyway, this worked:

{% capture line_txt %}
{{ line_item.id }}
{% endcapture %}
{% assign str_id = line_txt | strip %}

str id: {{ order.metafields.sfc.[str_id].value }}