Twig conditional around form-group input value - header

very new to Twig and im trying to build a conditional to render if a form group with a nested input meets a specific value, else do something different. Here is the code, but it doe not seem to be rendering correctly when specific parameters are met. Am I doing this correctly? Any help would be appreciated. Thanks
{% set RespHeader %}{{ form-group.input.value }}{% endset %}
{% if RespHeader == "Something" %}
<header id="header" class="responsive-section-label">
{% else %}
<header id="header" class="section-label">
{% endif %}

Twig will translate your form-group variable as form minus group.
Either don't use dashes or use the array notation e.g.
{% set RespHeader %}{{ _context['form-group'].input.value }}{% endset %}
note: _context is a special variable which contains all known variables to the template

Related

Shopify Liquid tag nested in liquid tag - any workaround?

I'm new to Shopify and Liquid. I know that you can't nest a liquid tag within another liquid tag ie:
{% something {{ something_else }} %}
I was wondering if there is a workaround for this kind of scenario? Possibly involving 'capture' or clever use of 'raw'?
I'm building a site that uses product tags to denote which chocolates go in which products (collection of chocolates). On the product page I can easily return the tags as a list:
<ul class="chocolates-menu">
{% for tag in product.tags %}
<li>{{ tag }}</li>
{% endfor %}
</ul>
However, I'd like to render snippets with file names to match the names of the tags (these will contain an image, chocolate name and chocolate description) ie:
<li>{% render '{{ tag }}' %}</li>
The closest I've got is:
{% for tag in product.tags %}
{% capture chocolate_tag %}
{% raw %}{% render{% endraw %} {% raw %}'{% endraw %}{{ tag }}{% raw %}' %}{% endraw %}
{% endcapture %}
<li>{{ chocolate_tag }}</li>
{% endfor %}
This will output the correct code but as text on the page (rather than parsing it). ie: {% render 'Tag Name Here' %} simply as the text of the list item. Any help from brighter folk, is much appreciated. Thanks.
I would suggest creating a snippet for all your chocolates and using the tag as a variable to output what is needed.
Here is a visual representation of what I mean and is kinda clearer from your discussion with #Fabio Filippi
snippets/chocolate.liquid
{% assign tag_image = tag | append: '.png' %}
{% case tag %}
{% when 'diet' %}
<img src="{{ tag_image | file_img_url: '100x' }}" class="responsive" />
{% when 'dark' %}
<div>My dark chocolate HTML</div>
{% when 'white' %}
<div>My white chocolate HTML</div>
{% endcase %}
and how to use:
{% render 'chocolate', tag: tag %}

How to avoid calling content when two tags are partially the same in Shopify

I am currently trying to display content based on product tags that are assigned to products in Shopify.
This is working ok, but my problem is that I have two tags that contain partially the same tag name, so I am getting both sets of content appearing on the front end.
One tag shows a field that is required "r-[tag-name]" and the other shows the same field but it is not required "[tag-name]".
Obviously I know this is due to the fact that I am using 'contains' so the logic is true for both when either tag is applied, but I have tried using '==' (equals) but it when I do, nothing appears at all :/
What I would like to know is, what do I need to change so that the statement is only true if a tag exists that is exactly the same as the if statement.
I am new to Liquid so any help would be greatly appreciated!
<!--Convert the tags into a string by joining them with COMMA-->
{% assign productTags = product.tags | join: ', ' %}
<!--Now Check for the desired tag name-->
{% if productTags contains 'r-custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input class="required" id="name-one" type="text" name="properties[Name One]">
</p>
{% endif %}
{% if productTags contains 'custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input id="name-one" type="text" name="properties[Name One]">
</p>
{% endif %}
I need to change so that the statement is only true if a tag exists that is exactly the same as the if statement
This should do it:
{% for tag in product.tags %}
{% if tag == 'r-custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input class="required" id="name-one" type="text" name="properties[Name One]">
</p>
{% break %}
{% endif %}
{% if tag == 'custom-name-one' %}
<p class="line-item-property__field">
<label for="name-one">Name One:</label>
<input id="name-one" type="text" name="properties[Name One]">
</p>
{% break %}
{% endif %}
{% endfor %}
I added {% break %} which will
Causes the loop to stop iterating when it encounters the break tag.
I assumed that once the tag is found, you don't need need to continue looping through the rest of the tags!

Shopify Theme Development - For loop that checks if article.tags contains a sections variable

I am trying to pull through related blog posts if the article.tags == the string given within the section settings.
I have tried a few different variations but to no effect. My code looks like this (don't worry about the content within the if loop, this is all fixed into shape by the CSS):
{% for article in blogs.news.articles limit:1 %}
{% if article.tags == section.settings.brand-news-tag | strip_html %}
{% assign image_src = article.image.src | img_url: 'large' %}
<div class="brand-page-featured-news-blogs">
<div class="brand-page-featured-news-article">
<div class="brand-page-featured-news-article-image" style="background-image: url({{ image_src }})">
<div class="brand-page-featured-news-article-image-contain">
<div class="brand-page-featured-news-article-image-overlay">
</div>
</div>
</div>
<div class="brand-page-featured-news-article-contain">
<h6 class="brand-page-featured-news-article-title">{{ article.title }}</h6>
<div class="brand-page-featured-news-article-content">
<p class="brand-page-featured-news-article-published">{{ article.published_at | date: "%d %B 20%y" }}</p>
<p class="brand-page-featured-news-article-text">{{ article.content }}</p>
<div class="brand-page-featured-news-article-button">
<div class="brand-page-featured-news-article-button-text">
Read More
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endfor %}
{% schema %}
{
"name": "Featured News",
"settings": [
{
"id": "brand-news-tag",
"type": "text",
"label": "Brand News Tag",
"default": "brandnametag"
}
]
}
{% endschema %}
{% stylesheet %}
{% endstylesheet %}
{% javascript %}
{% endjavascript %}
This is the line in question:
{% if article.tags == section.settings.brand-news-tag | strip_html %}
I have tried to use a few other variations like without the '| strip_html'. I have tried to put it inside quotes like this {% if article.tags == "'" and section.settings.brand-news-tag and "'" %}. I have also tried to use 'contains' opposed to an '=='.
How can I use a variable within the if statement?
I have tried using -
{% if article.tags contains section.settings.brand-news-tag %}
I have also tried without any if statement narrowing down the blogs.news. this works as expected. Meaning it is something to do with this if statement not comparing to the blog tags. Although I have directly copied the blog tag in from the blog post to go into the variable within the section.
This also doesn't work -
{% for article in blogs.news.articles limit:1 %}
{% if section.settings.brand-news-tag != '' %}
{% assign blogfilter = section.settings.brand-news-tag | strip %}
{% endif %}
{% if article.tags contains blogfilter %}
This also doesn't work (Goodfellow is the tag copied) -
{% for article in blogs.news.articles limit:1 %}
{% if article.tags contains 'Goodfellow' %}
Here are some images of the blog side of things:
If you look at the article object in Shopify documentation then article.tags return an array. So an array cannot be compared with a string using == equals operator. You are looking for contains as explained in the logical and comparison operators documentation.
So your code will become
{% if article.tags contains section.settings.brand-news-tag %}
Moreover, you don't need strip_html as the field type is text. So Shopify will take care of it. You can use strip filter to remove any space and tabs from the start and end of string just to be extra sure.
String Filters
For your particular scenario, you don't need the limit: 1 inside for loop because you don't know that first object will contain the tag. So you need to iterate over all the objects and break out of loop if condition is satisfied. Sample code
{% for article in blogs.news.articles %}
{% if article.tags contains 'Goodfellow' %}
{{article.tags}}
{% break %}
{% endif %}
{% endfor %}

Filter out collection name from product tag list (display) shopify

I would love to know how to remove from display tags that are used to automatically create collections (they appear in other product section).
For example:
$125
COLLECTION : BUSINESS
TAGS: AUTUMN BUSINESS BLACK
So that BUSINESS tag (which is used to form a BUSINESS collection ) is filtered out.
Tries the following 'straightforward' solution:
{% for tag in product.tags %}
{% unless tag == 'Business' or tag == 'Vintage' or tag == or tag == 'Boho' %}
display {{ tag }} link
{% endunless %}
{% endfor %}
Which did not see to Work
Thanks
Sometimes multiple conditions in if statements don't work so well in liquid. (See here and here.)
You could try something like this instead:
{% assign excluded_tags = "Business,Vintage,Boho" | split: "," %}
{% for tag in product.tags %}
{% unless excluded_tags contains tag %}
{{ tag }}
{% endunless %}
{% endfor %}
EDIT:
I just tested your code again, and even with the typo or tag == or..., it still works fine for me (just a warning on save).
Another suggestion is perhaps it's got to do with capitalisation. E.g. If you have a tag BUSINESS, then tag == 'Business' is not going to work. The capitalisation needs to be consistent.
EDIT 2:
From comment below:
I was thinking how to automatically populate excluded tags by the names of the collections of a product.
You can use map to get an array of collection titles:
{% assign excluded_tags = product.collections | map: 'title' %}
Your straightforward is incomplete.
{% for tag in product.tags %}
{% unless tag == 'Business' or tag == 'Vintage' or tag == <missing_value_here> or tag == 'Boho' %}
display {{ tag }} link
{% endunless %}
{% endfor %}
The third condition is empty hence could be the reason it is failing.
Also as mentioned in another answer by Steph, multiple conditions may be unstable at times, if that the case try this:
{% for tag in product.tags %}
{% unless tag == collection.title %}
display {{ tag }} link
{% endif %}
{% endfor %}
It will take care of any future collections as well.
P.S. This is assuming that the page where the tags are displaying contains a collection url.

Django template inheritance the other way round

Django template system lets you easily specify a template and fill it with different data using extends and blocks.
What I need to do is to have several templates, filled with the same data (blocks) while avoiding code repetition. It sounds like a usecase for templatetags but consider this example:
<div class="container">
{% get_tags page as tags %}
{% if tags %}
<div class="ribbon">
<span class="ribbon-inner">{{ tags|join:' | ' }}</span>
</div>
{% endif %}
</div>
If I wanted to display the tags in another template using a different html elements/classes I would have to create at least two templatetags (has_tags and get_tags) or include html in templatetags code.
I'd like to have something like this:
#common.html
{% block tags %}
{% get_tags page as tags %}
{% if tags %}
<div class="ribbon">
<span class="ribbon-inner">{{ tags|join:' | ' }}</span>
</div>
{% endif %}
{% endblock %}
#template_A.html
{% include common.html %}
<div class="container-1">
{% block tags %}
{{ block.super }}
{% endblock %}
</div>
#template_B.html
{% include common.html %}
{% block tags %}
{% get_tags page as tags %}
{{ tags|join:', ' }}
{% endblock %}
The problem is that include renders the template first, therefore it doesn't work this way. There are a lot of similar points in the file I'm editing, so creating and including template for each of them is not a great solution either.
Any thoughts?
Well, this is my solution:
#templateA.html
{% include "_common.html" with parent_file="_templateA.html" %}
#templateB.html
{% include "_common.html" with parent_file="_templateB.html" %}
#_templateA.html
<i>{% block tags %}{% endblock %}</i>
#_templateB.html
<b>{% block tags %}{{ tags|join:' & ' }}{% endblock %}</b>
#_common.html
{% extends parent_file %}
{% block tags %}
{% if not block.super %} # this does the trick
{{ tags|join:' I ' }}
{% else %}
{{ block.super }}
{% endif %}
{% endblock %}
This allows having HTML templates in _templateA.html and _templateB.html. If the block is left empty, it is filled with default from _common.html, while it can be overriden in _template.
It would be nice to override the block tag to avoid code repetition in _common.html but the following implementation fails on block.super() because of missing context.
#register.tag('overridable_block')
def overridable_block(parser, token):
from django.template.loader_tags import do_block
block = do_block(parser, token)
if block.super():
return block.parent
return block
Haven't found a way past this yet.