How to add collection.liquid to an existing page? - shopify

In Shopify, I'm trying to take the template collection.liquid and render it in another page, just like embedding it. But i'm not sure how to accomplish that.
{% paginate collection.products by 50 %}
{% include 'breadcrumb' %}
{% if settings.show_sort_by and collection.products_count > 1 %}
{% include 'collection-sort' %}
{% endif %}
{% if current_tags.size > 0 %}
<h1>{{ current_tags.first }}</h1>
{% else %}
{% endif %}
{% if collection.description.size > 0 %}
<!--START HERO-->
<!--END HERO-->
{% endif %}
<!--START PRODUCT GRID-->
<section class="product-grid twelve columns alpha omega">
<div id="collection_hero" class="collection_hero_class">
<img src="http://carnegie.org/fileadmin/Media/News/press_releases/whitehouse.JPG">
</div>
{% if collection.products.size > 0 %}
{% for product in collection.products %}
{% include 'product-grid-item' %}
{% endfor %}
{% else %}
<p id="no-products" class="animated fadeInUpBig">There aren't any products in this collection!</p>
{% endif %}
</section>
<!--END PRODUCT GRID-->
{% include 'paging' %}
{% endpaginate %}

I've been trying to do the same thing and kept getting errors.
Fixed it by making a new Snippet called list-collections and copying everything from list-collections.liquid into that. Then made a page template called page.list-collections.liquid and pasted this code into that before /div: {% include 'list-collections' %}
Then, I made a new page using the page.list-collections template, and entered my introductory text, images etc in that, which displays above product collections on the page when published :)

Copy everything that's in collection.liquid and paste it into a new snippet (let's say you call it collection-copy.liquid).
Then, in the page you want to add the collections page to, just add {% include 'collection-copy' %}
That should just dump everything that's in collection-copy.liquid and output it to your page.

The simplest way to do so is to :
Create a new page template for example : page.list-collections
Then place under : {{ page.content }} this line :
{% section 'list-collections-template' %}
Now create a new page in Shopify then select the new page template.
Normally you should be able to add new collections in the "Customize" section of your page !

Related

Display product loop based on tag only in Shopify

I'm trying to display a product loop in a Collection template on Shopify. I want to pull all products with a specific tag 'Hydrate' to display within the Collection.
The template file is collection.custom.liquid and so far I have the below:
{% for product in collection.products %}
{% if product.tags contains "Hydrate" %}
Do Something
{% endif %}
{% endfor %}
But it doesn't display anything. I have confirmed I do have the tags setup correctly and I'm even using the exact same case sensitivity in case thats a thing.
If someone could point me in the right direction to display products from the tag 'Hydrate' in a custom collection template that would be great! Thanks so much
EDIT
I've now altered the code and moved it outside any pagination, and added for each product to the below. It now displays however it keeps displaying the same tags 5 times over on the page. Is there an issue with my syntax? Any ideas?
{% for product in collection.products %}
{% for product in products %}
{% if product.tags contains "Hydrate" %}
<p>{{ product.title }}</p>
{% endif %}
{% endfor %}
{% endfor %}
EDIT 2
In case anyone else has this same issue in future, the below code is what has ended up working and displays the correct tags, the correct amount of times:
{% assign products = collection.products %}
{% for product in products %}
{% if product.tags contains "Hydrate" %}
<p>{{ product.title }}</p>
{% endif %}
{% endfor %}
Your code is correct, so it might be a pagination issue. For example, there are no product with this tag in the first page but there are in the second one.

Shopify' s all_products[ ] does only accept title

For a client I'm building a way to choose what products are shown in the recommended products section on the product page. To achieve this I thought about inserting the handles from the products I'd like to display into the tag part of the product.
So I'm able to loop over all the tags from the product and then for every tag I'd take the product object and display it. The problem is this code doesn't seem to work:
{% for tag in tags %}
{% for single_product in all_products[tag] %}
{{ single_product }}
{% endfor %}
{% endfor %}
This code does work:
{% for tag in tags %}
{% for single_product in all_products[tag].title %} <---- Added .title
{{ single_product }}
{% endfor %}
{% endfor %}
Sadly, I need the entire product object to display it instead of only the product title. How do I achieve this in shopify?
Side info: This code is placed inside of the framework--product-recommendations.liquid file
The solution was using the collection instead of the all_product. I create a collection containing all product and was perfectly able to loop over it.
My code looks like this now:
{% for tag in tags %}
{% for single_product in all_the_products %}
{% if tag == single_product.handle %}
<div class="product-recommendations--item">
{%
render 'framework--product--item',
product: single_product,
view: 'grid'
%}
</div>
{% endif %}
{% endfor %}
{% endfor %}
all_the_products is assigned to a collection containing all the products.

How can I add a check to see if a collection on Shopify is available / published?

How can I correct "Liquid error: comparison of String with 0 failed" when a collection is not published/ available?
If I make the collection unavailable/ not published I have
"Liquid error: comparison of String with 0 failed"
on the frontend.
Removing
{% if collections['catalogue'].products_count > 0 %}
shows "coming soon"
This is the line in question I think but I need to check there are products.
I've also tried adding
{% if collections['catalogue'] %}
I need the Catalogues section to be completely hidden until it's avaialble
{% if collections['catalogue'].products_count > 0 %}
<div class="contain collection collection--home" data-intro="fade-in-up">
<header role="banner" class="collection__title">
<h1 class="h3 font--condensed text--upper">Catalogues</h1>
</header>
<div class="collection-grid">
{% for product in collections['catalogue'].products limit:1 %}
{% include 'collection-item' %}
{% else %}
<p>{{ 'collections.general.no_matches' | t }}</p>
{% endfor %}
</div>
</div>
{% endif %}
sorry I'm a liquid and Shopify nooob :-/
You can check the publishing date since that is null when is not published.
{% if collections['catalogue'].published_at != empty %}
// your code
{%- endif -%}
Please have in mind that you are checking for products count in your code but you are asking for collection availability which are 2 different things. A collection can be unavailable and still have products.
If you want to check for products swap it for:
{% if collections['catalogue'].products.size > 0 %}
// your code
{%- endif -%}

Assigning a collection to a custom created collection page in Shopify?

I am using a free Venture theme on Shopify and i am trying to make a custom collection page.
I found a solution in stackoverflow but it was able to help someplace.
How to add collection.liquid to an existing page?
The summery of the solution is:
Copy everything that's in collection.liquid and paste it into a new snippet (let's say you call it collection-copy.liquid).
Then, in the page you want to add the collections page to, just add {% include 'collection-copy' %}
This solution worked well but there is one more issue for me. In the custom created page it says "Sorry, there are no products in this collection" In the customization of the same page there is a "collection" section. But in the "collection" section there is no option to choose a collection. There is only "Enable tag filtering" and "Enable sorting" check boxes.
Webpage: https://mottomfreedom.com/pages/less-is-more
Do you have any idea of assigning a collection with this custom created snippet?
{% paginate collections[settings.frontpage_collection].products by 20 %}
<div class="page-width">
<header class="grid medium-up--grid--table section-header small--text-center">
<div class="grid__item medium-up--one-half section-header__item">
<h1 class="section-header__title">
{{ collection.title }}
{% if current_tags %}
– {% assign title_tags = current_tags | join: ', ' %}
{{ title_tags }}
{% endif %}
</h1>
{% if collection.description != blank %}
<div class="section-header__subtext rte">
{{ collection.description }}
</div>
{% endif %}
</div>
<div class="grid__item medium-up--one-half medium-up--text-right section-header__item">
{% section 'collection-filters' %}
</div>
</header>
<div class="grid grid--no-gutters grid--uniform">
{% for product in collection.products %}
<div class="grid__item small--one- medium-up--one-third">
{% include 'product-card', product: product %}
</div>
{% else %}
{% comment %}
Add default products to help with onboarding for collections/all only.
The onboarding styles and products are only loaded if the
store has no products.
{% endcomment %}
{% if shop.products_count == 0 %}
<div class="grid__item">
<div class="grid grid--no-gutters grid--uniform">
{% assign collection_index = 1 %}
{% for i in (1..10) %}
{% case i %}
{% when 7 %}
{% assign collection_index = 1 %}
{% when 8 %}
{% assign collection_index = 2 %}
{% when 9 %}
{% assign collection_index = 3 %}
{% when 10 %}
{% assign collection_index = 4 %}
{% endcase %}
<div class="grid__item small--one-half medium-up--one-fifth">
<a href="/admin/products" class="product-card">
<div class="product-card__image-container">
<div class="product-card__image-wrapper">
<div class="product-card__image">
{% capture current %}{% cycle 1, 2, 3, 4, 5, 6 %}{% endcapture %}
{{ 'product-' | append: current | placeholder_svg_tag: 'placeholder-svg' }}
</div>
</div>
</div>
<div class="product-card__info">
<div class="product-card__name">{{ 'homepage.onboarding.product_title' | t }}</div>
<div class="product-card__price">
$19.99
</div>
</div>
<div class="product-card__overlay">
{% assign view_string_length = 'products.product.view' | t | size %}
<span class="btn product-card__overlay-btn {% if view_string_length > 8 %} btn--narrow{% endif %}">{{ 'products.product.view' | t }}</span>
</div>
</a>
</div>
{% assign collection_index = collection_index | plus: 1 %}
{% endfor %}
</div>
</div>
{% else %}
{% comment %}
If collection exists but is empty, display message
{% endcomment %}
<div class="grid__item small--text-center">
<p>{{ 'collections.general.no_matches' | t }}</p>
</div>
{% endif %}
{% endfor %}
</div>
{% if paginate.pages > 1 %}
<div class="pagination">
{{ paginate | default_pagination | replace: '« Previous', '←' | replace: 'Next »', '→' }}
</div>
{% endif %}
</div>
{% endpaginate %}
You are right about giving some time before accepting an answer :)) The solution worked but forced me to create 1 page and 4 liquid files per collection. And at the end, i figured out that some sections like "collection.list" doesn't directs to the page which i have created. I think you were talking about this at the beginning of the answer :)
After that, i found a much better solution. Just creating a new section.liquid file and placing it in "collection.liquid" with an "if" statement solved my problem.
{% if collection.handle == 'less-is-more' %}
{% section 'custom-featured-products-LESSisMORE' %}
{% endif %}
But in any way, i'm grateful for your interest. Thank you very much Dave.
It looks like there's nothing defining the collection variable anywhere.
I would suggest changing the beginning of your code snippet from:
{% paginate collections[settings.frontpage_collection].products by 20 %}
To:
{% assign collection = collections[settings.frontpage_collection] %}
{% paginate collection.products by 20 %}
There is an implicit collections variable whenever you're on a page that includes /collections/[something] in the URL, but when you're on a URL that's /page/[something], you have an implicit page variable in Liquid instead.
Note: if the collection set in your theme's value for settings.frontpage_collection isn't the one you want, you can possibly:
a. Change the value using the 'Customize' link beside your theme (most easily found on the /admin/themes page), useful if you're not going to use that setting for anything else;
b. Hard-code a collection handle, eg: collections['i-am-sure-this-will-never-change'], but hard-coded strings are ugly and should generally be avoided;
c. Create your own theme setting by adding an entry to config/settings_schema.json - see https://help.shopify.com/en/themes/development/theme-editor/settings-schema if you're still getting up to speed with custom theme settings; or
d. If all your content is in a section, you can use section settings (similar to theme settings) to make a variable that's tied specifically to just that block of code.
If you need to make these special pages for multiple collections, and each of these pages is largely reusing the same code, you can make your life easier by moving the common code to a snippet and passing variables to it from your page template. To do so:
Create a file in the 'snippets' folder of your theme. (For this example, let's say the file is called collection-in-page.liquid. We will be passing a collection into this snippet, so you can remove the assign statement.
In your page-specific template, figure out what the collection handle is going to be
a. This might be hard-coded, or it might be something you could look up by using metafields or tags on the page. Examples:
{% assign collection_handle = 'hardcoded-handle' %}, {% assign collection_handle = page.metafields.related_items.collection %}
In your page template, include the snippet you created. I find it helps to explicitly pass any variables I want to use, like so:
{% include 'collection-in-page', collection: collections[collection_handle] %}
Hope this helps!

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.