How can I split a string by newline in Shopify? - shopify

I have a field in my settings.html where I am expecting the user to input multiple paragraphs separated by two newline characters. I would like to split this string of input into an array of strings, each representing a paragraph.
I would like to do something like this:
{% assign paragraphs = settings.intro | split: '\n' %}
{% for paragraph in paragraphs %}
<p>
{{ paragraph }}
</p>
{% endfor %}
I can't seem to figure out how to refer to the newline character in Liquid. How can I go about doing this? Is there some kind of work around?

Try this:
{% assign paragraphs = settings.intro | newline_to_br | split: '<br />' %}
{% for paragraph in paragraphs %}<p>{{ paragraph }}</p>{% endfor %}

#josh-browns answer got me pretty much there and might be enough for most instances. However, I had some blank paragraphs coming through from user generated double lines.
Denilson Sá Maia comment of strip_newlines did not help with my markdown processor so I checked if each line was empty manually before outputting the paragraph.
{% for paragraph in paragraphs %}
{% assign paragraph-length = paragraph | number_of_words %}
{% if paragraph-length > 0 %}
<p>{{ paragraph }}</p>
IMAGE HERE
{% endif %}
{% endfor %}
This doesn't solve the blanks in the array, for that I iterated over the array to create a new one, with only valid content. It would be really nice if there was a filter that worked on arrays, not just hashes.
{% assign all-paragraphs = content | strip | newline_to_br | strip_newlines | split: "<br />" %}
{% assign paragraphs = site.emptyArray %}
{% for paragraph in all-paragraphs %}
{% if paragraph and paragraph != "" and paragraph != site.emptyArray %}
{% assign paragraphs = paragraphs | push: paragraph %}
{% endif %}
{% endfor %}

If you do, in fact, need Shopify to split by newlines for any reason where you don't iterate with a for loop afterwards, it is indeed possible:
{% assign paragraphs = settings.intro | split: '
' %}
{% for paragraph in paragraphs %}
<p>
{{ paragraph }}
</p>
{% endfor %}
ie. you need to type an explicit newline into your source code.
This is due to the way Liquid works, quoting from the documentation about Types:
Liquid does not convert escape sequences into special characters.

Related

working with 'strings' as 'arrays' in shopify liquid

I am trying to display color boxes next to items based on item varients. However, it has been giving me weird results in my array. Yes I know there are no real arrays in liquid. I have two options below. The first one doesnt work. It gives me things like "background-color: [''''''' ". Along with all the correct ones too.
So the second option i just hard coded all the colors and checked against that. This works as long as the colors are in order... but if the colors are not in order than it will display duplicates.
New to liquid but this seems super ugly and probably means i am doing it wrong.
<div class="color-box-wrapper">
{% assign values = '' %}
{% for variant in product.variants %}
{% assign value = variant.option2%}
{% unless values contains value %}
{% assign values = values | append: ',' | append: value %}
{% assign values = values | split: ',' %}
{% for color in values %}
{% if color.size > 0%}
<div class="product-color-box" style="background-color:{{color}}"></div>
{% endif %}
{% endfor %}
{% endunless %}
{% endfor %}
</div>
THIS WAY KINDA WORKS BUT SEEMS HACKY.
<div class="color-box-wrapper">
{% assign realColors = 'yellow, blue, white, burgandy, black, red, green, purple, beige, light_brown' | split: ", "%}
{% assign values = '' %}
{% for variant in product.variants %}
{% assign value = variant.option2 | downcase%}
{% unless values contains value %}
{% assign values = values | append: ',' | append: value %}
{% assign values = values | split: ',' %}
{% for color in values %}
{% if realColors contains color %}
<div class="product-color-box" style="background-color:{{color}}"></div>
{% endif %}
{% endfor %}
{% endunless %}
{% endfor %}
</div>
It might work better to use the product.options_with_values field, something like this:
{% assign color_option = product.options_with_values | where: 'name', 'color' | first %}
<h1>Color option is in position {{ color_option.position }}!</h1>
<h2>Array of all values is: {{ color_option.values | json }}</h2>
{% for value in color_option %}
<h3>Gimmie a {{ value }}!! {% if value == color_option.selected_value %}(Selected){% endif %}</h3>
{% endfor %}
It's a bit trickier if your colours are not CSS-recognized colour names, but there are certainly a number of things you can do for that. I typically prefer adding a CSS layer that can translate colour values into the appropriate display values (either background images or colour hex-codes). Some ideas are:
Add a data attribute or a class to your element (usually using the | handle filter to standardize the output) and use a CSS sheet to assign background images or colours appropriately
Create a section with blocks that allows you to map colour values to hex codes. If you are creating this for someone other than yourself, it would allow the merchant to set up the colours themselves and fine-tune all the shades.
Use metafields on your product that can generate the correct colour code using the options as the lookup. (Eg: If you create a metafield namespace on your products of product.metafields.colors and use the colour names as the keys and hex codes as the values, you can output {{ product.metafields.colors[value] }} to get the right computer colour. (This generally requires installing an app to manage - though metafields themselves are native Shopify functionality, Shopify doesn't have any native way to set them in the admin)
Hope this helps!
References:
Shopify Liquid Reference - Product objects: https://help.shopify.com/en/themes/liquid/objects/product#product-options_with_values
Shopify Liquid Reference - Product Option objects (from options_with_values): https://help.shopify.com/en/themes/liquid/objects/product_option

how to split the string in django template?

i am trying to split the string in template using custom template filter. But i got an error
TemplateSyntaxError at /job/16/
'for' statements should use the format 'for x in y': for skill in form.instance.skills | split : ","
Here it is my filter
#register.filter(name='split')
def split(value, key):
"""
Returns the value turned into a list.
"""
return value.split(key)
this is my template
<h4>Skills</h4>
{% for skill in form.instance.skills | split : "," %}
{{ skill }}
{% endfor %}
Thanks
Split is a custom filter, don't forget to create your filter, and to load it in your HTML page.
Documentation for Django 4.0: https://docs.djangoproject.com/en/4.0/howto/custom-template-tags/
<h4>Skills</h4>
{% with form.instance.skills|split:"," as skills %}
{% for skill in skills %}
{{ skill }}<br>
{% endfor %}
{% endwith %}
For extract character string, use filter cut:
Phone
this removes the scripts from the string.
The direct for loop works too, you just have to remove the spaces in the syntax:
<h4>Skills</h4>
{% for skill in form.instance.skills|split:"," %}
{{ skill }}
{% endfor %}

Liquid - Convert Array to Lowercase

I'm using Shopify and want to hook into customer tags, however they are case sensitive. So {% if customer.tags contains "wholesale" %} is not the same as {% if customer.tags contains "Wholesale" %}. My client may or may not stick to one case when applying tags so I want to guard against that in the future.
I would like to take an array, customer.tags, and convert all of the values to lowercase. I'm trying to work out the logic but am having trouble.
I want to put customer.tags into a new array which isn't working.
{% assign newArray = customer.tags %}
{{ newArray }}
What am I doing wrong?
You could use the downcase filter for this:
{% assign contains_wholesale = false %}
{% for tag in customer.tags %}
{% assign lowercase_tag = tag | downcase %}
{% if lowercase_tag == 'wholesale' %}
{% assign contains_wholesale = true %}
{% endif %}
{% endfor %}
Note: downcase just works for ASCII characters. If you need to search for strings with accented letters or other Unicode characters then this won't be enough.
if you would like to keep customer.tags as an array so you can keep using contains in a simple if statement (like your example). You could also chain a couple of liquid filters together to turn all of the strings within the array to lowercase.
Example:
{% assign lowercaseTags = customer.tags | join: ',' | downcase | split: ',' %}
{% assign randomString = 'WholeSale' | downcase %}
{% if lowerCaseTags contains randomString %}
{% comment %}
Will now match regardless of case sensitivity
{% endcomment %}
{% endif %
Explanation:
Join filter: Turn the array into a string seperated by ,
Downcase filter: make the whole string lowercase
Split filter: opposite of join, recreates the array from the string based on the character used in join ,
Another solution as you use the "contains" operator would be to skip the "w".
Something like {% if customer.tags contains 'holesale' %} should work.

Looping through metafields in shopify

I need to display n number of images for a product in shopify.
I have stored number of images in a metafields and created a loop for it.
Then each image's name is stored in a metafield, which i am trying to get with help of loop.
{% assign earrings = product.metafields.earrings %}
{% for i in (1..earrings.total-earrings) %}
{% assign earring = 'product.metafields.earring-' | append:i %}
{{ earring.name }}
{% endfor %}
This loop is giving me values for earring like:
product.metafields.earring-1
product.metafields.earring-2
but when i am trying to read value of metafield earring.name, i am not getting any output. I think because product.metafields.earring-1 is a string.
Is there any possible way to loop through metafields like this and get values?
Just in case it's helpful for someone.
Here's the updated code:
{% assign earrings = product.metafields.earrings %}
{% for i in (1..earrings.total-earrings) %}
{% assign dummy = 'earring-' | append:i %}
{% assign earring = product.metafields[dummy] %}
{{ earring.name }}
{% endfor %}

Remove variants from variants array on product in Liquid

Good evening! I am trying to remove variants from the variant array on a product using pure Liquid(Shopify templating language). I would only like to use javascript as a last resort.
Below is where I am so far. Anything that is the variant in the if check needs to be removed from currentProduct.variants.
{% assign currentProduct = product %}
{% for variant in currentProduct.variants %}
{% include 'shappify-variant-is-csp' %}
{% if csp_variant != 1 %}
//need to remove the object that meets this if statement
{% endif %}
{% endfor %}
I'm pretty sure you're going to need to use some javascript to achieve this. Take a look at this article on the Shopify wiki: How do I remove sold out variants from my options drop-downs.
Modifying the code in that article for your situation, you'll want something like this:
{% for variant in product.variants %}
{% include 'shappify-variant-is-csp' %}
{% if csp_variant != 1 %}
jQuery('.single-option-selector option').filter(function() { return jQuery(this).html() === {{ variant.title | json }}; }).remove();
{% endif %}
{% endfor %}
jQuery('.single-option-selector').trigger('change');