Filter products through tags in Shopify - html

I am trying to pull only the products from a collection that have a certain tag. This is my way of creating sub-collections since Shopify doesn't do this. My code doesn't seem to be working, and I can't figure out why it isn't working. I am doing this on the collection.liquid page. It is just printing the headings to the screen, but not the list of products. Any ideas?
{% if collection.handle == "all" %}
<!-- All Collections -->
<div id="collections">
<h2>Brave Bracelets</h2>
<div class="product-list clearfix">
<h3>Cerulean</h3>
<ul>
{% for product in collections.brave-bracelets.products %}
{% capture alt_attr %}{{ product.title }} by The Brave Collection{% endcapture %}
{% if product.tags contains "cerulean" %}
<li>
<img src="{{ product.featured_image | product_img_url: 'compact' }}" alt="{{ alt_attr }}" />
<h3>{{ product.title }}</h3>
</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div><!-- #collections -->
{% endif %}

There is a minor mistake on your capture line, which should be:
{% capture alt_attr %}{{ product.title }} by The Brave Collection{% endcapture %}
But other than that, your code worked fine for me. I pasted it into collection.liquid and changed the collection "brave-bracelets" and tag "cerulean" to a collection and tag of my own, and it displayed the list of products as expected. Maybe double check that you do have products with the tag "cerulean" in the collection "brave-bracelets"...

Related

Twig set reusable piece of html

I'm creating some templates with Twig and have an issue.
I'm trying to load a piece of html that is used several times troughout a webshop. So my idea is to create a reusable piece of code that I can load everytime when needed.
The problem I'm facing is that when I do a for loop and then include that piece of code I get an empty return. With other words my code doesn't recognize the data that need to be loaded for each product in the for loop. It returns empty info boxes.
To clarify:
I have a main template index.html which calls a snippet to include some products (don't look at rain extension!!):
{% if featured %}
{% include 'snippets/products.rain' with {'products': featured, 'type': 'grid'} %}
{% endif %}
My products.rain snippet looks like this:
{% if type %}
{% if type == 'grid' %}
{% for product in products %} {# Products in this case = feautured products #}
<li class="item clearfix">.... etc etc .... </li>
{% endfor %}
{% elseif type == 'other-layout' %}
<div class="item">.... etc etc .... </div>
{% endif %}
{% endif %}
In the for loop there's html that's for 95% the same as in each for loop. I want to place that code inside a block that can be included in the for loops.
So what I did was:
{% set product_html %}
.... a lot of html ....
<a href="{{ product.url | url }}" title="{{ product.fulltitle }}">
<img src="{{ product.image }}" width="100" height="100" alt="{{ product.fulltitle }}"/>
</a>
{% endset %}
And then included in the for loop, like so:
{% if type %}
{% if type == 'grid' %}
{% for product in products %} {# Products in this case = feautured products #}
<li class="item clearfix">{{ product_html | raw }}</li>
{% endfor %}
{% elseif type == 'other-layout' %}
<div class="item">{{ product_html | raw }}</div>
{% endif %}
{% endif %}
However this returns the html that is set however with empty product.image and empty product.fulltitle.
I tried the same with set block, but that has the same result.
Is there anything I'm doing wrong....??
When you are using {% set %}, content inside your variable is not dynamic, it will only use data in your current context, see it live.
You can achieve your goal using 2 ways: using include or using macros.
As your piece of code for a product is small and not reused somewhere else, I suggest you to use macros:
{% macro product_html(product) %}
Current product is: {{ product }}
{% endmacro %}
{% import _self as macros %}
{% for product in products %}
{{ macros.product_html(product) }}
{% endfor %}
See it live

Shopify After 4 Products add a Horizontal Break

I'm trying to figure out how to add a horizontal break after 4 products within the Shopify product loop. Is this possible at all? I've looked through their documentation but it doesn't show the possibility of counting or iterating over the loop.
Currently my loop looks as follows:
{% if collection.all_products_count > 0 %}
<div class="w-col w-col-12">
<div class="product-feed w-clearfix">
{% for product in collection.products %}
<a class="product product-collection w-inline-block" href="{{ product.url | within:collection }}">
<div class="reveal">
<img src="{{ product.featured_image | product_img_url: 'original' }}" alt="{{ product.title | escape }}" class="product-photo">
<img src="{{ product.images.last | product_img_url: 'original' }}" alt="{{ product.title | escape }}" class="hidden">
</div>
<h3 class="product-title">{{ product.title }}</h3>
<div class="product-price">{{ product.price | money }}</div>
<span class="shopify-product-reviews-badge" data-id="{{ product.id }}"></span>
</a>
{% endfor %}
</div>
{% assign count = paginate.pages %}
{% for part in (1..count) %}
<li {% if paginate.current_page == part %}class="active"{% endif %}>{{ forloop.index }}</li>
{% endfor %}
{% else %}
<p>Sorry, there are no products in this collection</p>
{% endif %}
It's fair explanation that you have not gone through the documentation properly. Refer this: - https://help.shopify.com/themes/liquid/objects/for-loops
Straight forward way to get this to work is add the following line before {% endfor %}
{% cycle '','','','<hr>' %} // or <br> if you prefer
<hr> gets added every time the forloop is iterating the 4th time. More on this - https://help.shopify.com/themes/liquid/tags/iteration-tags#cycle

How to link post categories in Jekyll

I've got the following code in my index.html for Jekyll. I'm trying to find a way to link the categories associated with each post to the actual post themselves. So, if a post contains the category "travel" I want to click on a link that says "travel" which will bring me to all posts categorized as such.
<ul class="post-list" style="list-style-type: none;">
{% for post in paginator.posts %}
{% unless post.categories contains 'portfolio' %}
<li>
<h3>{{ post.title }}</h3>
<span class="post-meta">{{ post.date | date: "%c" }}</span>
Filed In:
{% unless p.categories == empty %}
{% for categories in post.categories %}
{{ categories }} //problem area
{% endfor %}
{% endunless %}
{{ post.excerpt }} Find out more...<br><br>
</li>
{% endunless %}
{% endfor %}
</ul>
Figured it out. For anyone else wondering how to do the same, first setup a categories.html page in your root directory. This page will list all posts that meet a specific category. It does by turning the category names into named anchor slugs as such <a href="#{{ category | first | remove:' ' }}" and then the preceding code creates the actual named anchor div which displays the post associated with that category. Finally, under the page or section where you want to display the list of categories, you present the final bit of code which links to the named anchor section in your categories.html page.
First piece of code to go into Categories.html:
<h2>Posts by Category</h2>
<ul>
{% for category in site.categories %}
<li><strong>{{ category | first }}</strong></li>
{% if forloop.last %}
{% else %}
{% endif %}
{% endfor %}
</ul>
Second piece of code to go into Categories.html:
{% for category in site.categories %}
<div class="catbloc" id="{{ category | first | remove:' ' }}">
<h2>{{ category | first }}</h2>
<ul>
{% for posts in category %}
{% for post in posts %}
{% if post.url %}
<li>
<a href="{{ post.url }}">
<time>{{ post.date | date: "%B %d, %Y" }}</time> -
{{ post.title }}
</a>
</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
</div>
{% endfor %}
Third piece of code to go where you want to display your named anchor linked categories:
Filed In:
{% unless p.categories == empty %}
{% for categories in post.categories %}
{{ categories }}
{% endfor %}
{% endunless %}
Use the following CSS to prevent the sections from displaying prematurely before you click on them:
.catbloc:not(:target){
display: none;
}
Hope this helps!

In Jekyll How do I grab a post's first image?

In my index of blog posts I'd like to grab the first image from the post to display it in the index using just liquid so it works on github pages.
I have a feeling split is the way to go, but I'm not good with liquid.
I'd like to be able to get the image url and put it in a variable to style it.
The ideal solution would be something like:
{% for post in site.posts %}
<li>
{{post.content | first_image}}
</li>
{% endfor %}
Any ideas?
You can define a custom variable to your Front Matter called "image", so it's going to work like Wordpress's posts Featured Image:
---
image: featured-image.jpg
---
Note to remember where is your image saved. In my case, I created a directory called "imagens" (PT-BR here). Then, go to your index.html and add the image to your template, wherever you want. In my site it looks like this:
<ul class="post-list">
{% for post in site.posts %}
<li>
<h2>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
</h2>
<span class="post-meta">{{ post.date | date: "%b %-d, %Y" }},</span>
<span class="post-meta">por</span>
<span class="post-meta">{{ post.author }}</span>
</li>
//IMAGE
<img src="{{ site.baseurl }}/imagens/{{ post.image }}">
//IMAGE
{{ post.excerpt }}
<a class="btn btn-default" href="{{ post.url | prepend: site.baseurl }}">Continuar lendo</a>
{% endfor %}
</ul>
That's it.
Some solutions to your problem :
1 - Use the Post Excerpt tag Documentation is here
Your post :
---
layout: post
title: Testing images
---
## Title
Intro Text
![Image alt]({{ site.baseurl }}/assets/img/image.jpg "image title")
More intro text
Some more text blah !
Your template :
<ul>
{% for post in site.posts %}
<li>
{{ post.title }}
{{ post.excerpt }}
</li>
{% endfor %}
</ul>
As your image tag appears before the excerpt_separator (\n\n = two newlines) it will be in the post excerpt.
2 - Use your post's Yaml front matter to store your image's datas
Post :
---
layout: post
title: Testing images
images:
- url: /assets/img/cypripedium-calceolum.jpg
alt: Cypripedium Calceolum
title: Cypripedium Calceolum
- url: /assets/img/hello-bumblebee.jpg
alt: Hello bumblebee !
title: Hello bumblebee !
---
Intro here yo ! <-- THIS IS THE EXCERPT
Post body begin, and first image not in excerpt
{% assign image = page.images[0] %} <-- first element of the array is zero
{% include image.html image=image %}
Some more text blah !
{% assign image = page.images[1] %}
{% include image.html image=image %}
_includes/image.html (centralized in an include for standardization, but can be in the template) :
<img src="{{ site.baseurl }}{{ include.image.url }}" alt="{{ include.image.alt }}" title="{{ include.image.title }}">
The index page :
<ul class="posts">
{% for post in site.posts %}
<li>
<span class="post-date">{{ post.date | date: "%b %-d, %Y" }}</span>
<a class="post-link" href="{{ post.url | prepend: site.baseurl }}">{{ post.title }}</a>
{{ post.excerpt }}
{% assign image = post.images[0] %}
{% include image.html image=image %}
</li>
{% endfor %}
</ul>
Got it to work. Not sure how it will scale, but this liquid code loops through all the posts and grabs the source for the first image from a post and displays that post. I tested it with multiple images and it works as expected.
<ul>
{% for post in site.posts %}
<li>
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
<img {{ html }} />
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}
{{ post.title }}
</li>
{% endfor %}
</ul>
If you just need the image URL instead of the whole thing in img tag, you can use the following method.
Install Liquid filter match_regex:
gem install match_regex
Then add it to your Jekyll config:
plugins:
- match_regex
Create a capture snippet in your template:
{% capture post_first_image %}
{% assign hero_image = page.content | match_regex: '<img .*?src="([^"]+)"' %}
{% if hero_image == nil %}
{% assign hero_image = "/placeholder-image.png" | prepend: site_base %}
{% endif %}
{{ hero_image }}
{% endcapture %}
Template:
<meta property="og:image" content="{{ post_first_image | strip }}">
You can simply remove the if condition if you don't need placeholder image.
I've taken David's answer and found a way to get just the src attribute from the img tag.
{% assign foundImage = 0 %}
{% assign images = post.content | split:"<img " %}
{% for image in images %}
{% if image contains 'src' %}
{% if foundImage == 0 %}
{% assign html = image | split:"/>" | first %}
{% assign tags = html | split:" " %}
{% for tag in tags %}
{% if tag contains 'src' %}
<img {{ tag }} />
{% endif %}
{% endfor %}
{% assign foundImage = 1 %}
{% endif %}
{% endif %}
{% endfor %}

Jekyll Loop breaks on second iteration

I'm looping through two products - on the post view page I pull in a secondary post (in the example, a related recipe) which parses just fine on the first product page - on the second product page just {{ post.content }} won't parse. I can hack it with {{ post.content | markdownify }} - but I'd like to know why it's breaking. Here's the relevant code:
{% for post in site.categories.recipe %}
{% if post.products contains page.title and post.featured %}
<div class="row">
<div class="four columns">
<h4>{{ post.title }}</h4>
<ul>
<li>Serves {{ post.serves }}</li>
<li>Prep: {{ post.time }}</li>
<li>Share</li>
</ul>
{{ post.content }}
...
<!-- All tags are closed, the rest just isn't relevant -->
{% endif %}
{% endfor %}
Please find my solution with counter
<pre>
{% assign counter=0 %}
{% for post in site.posts%}
{% if post.category == 'blog' and counter < 2 %}
{% assign counter=counter | plus:1 %}
{{post.content}}
{% endif %}
{% endfor %}
</pre>
The markdownify filter is probably making it work because there might be special characters that aren't encoded in the content you're pulling from. I always forget to make my & into &.
If you're using the default Markdown interpreter Maruku, here's a list of the entities that might be giving you problems and their encoded equivalent. http://maruku.rubyforge.org/entity_test.html and more info on Maruku. http://maruku.rubyforge.org/maruku.html