I'm developing a Shopify website for a client who wasn't happy with the native related products section.
I started developing a custom section where my client can choose the products to display.
The only problem is I'm having a hard time find documentation relative to the product object. Or at least not understanding it well.
In my schema I added a product setting which allows to choose the product I want:
{
"type": "product",
"label": "Produit 1",
"id": "produit_premier"
}
This works fine, but the only output I'm getting is the name of my product.
How can I achieve displaying the product image?
Thanks for your help!
When you use the input type product in Shopify it returns to your handle of the product.
You need to use the all_products object to get more information regarding the product.
Update: you can use it like
This is the settings json code:
[UPDATED - FINAL]
Finished working on this, here's the final code:
<!-- GETS PRODUCT HANDLE AND ASSIGNS TO VARIABLE -->
<div class="hidden">
{% assign product = section.settings.produit_quatrieme %}
</div>
<!-- GETS PRODUCT FIRST IMAGE + LINK -->
{% for image in all_products[product].images %}
{% if forloop.first == true %}
<a href=" {{ all_products[product].url }} ">
<img src="{{image.src | img_url:"grande"}}" />
</a>
{% endif %}
{% endfor %}
<!-- GETS PRODUCT TITLE + LINK -->
{% for title in all_products[product].title %}
{% if forloop.first == true %}
<a href=" {{ all_products[product].url }} ">
<h2 class="ProductItem__Title Heading margin-none"> {{ all_products[product].title }} </h2>
</a>
{% endif %}
{% endfor %}
Add schema code to the section blocks instead of section settings. Then you can select as many products as you want.
{% for block in section.blocks %}
{% assign product = all_products[block.settings.produit_quatrieme] %}
<a href=" {{ product.url }} ">
<img src="{{product.featured_image| img_url:"grande"}}" />
</a>
<a href=" {{ product.url }} ">
<h2 class="ProductItem__Title Heading margin-none"> {{ product.title }} </h2>
</a>
{% endfor %}
If you want to display a single product then just add section instead of block, then no need to use for loop.
Related
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!
I'm new to Shopify. I have 5 blog categories (using multiple blogs) and I need to find a way to show each post in its own blog category. My code is currently populating the news articles and displaying the same ones in every category. How can I rewrite my for loop to loop through each category and display the articles only related to that category.
{% for article in blogs.news.articles %}
{% assign content = article.content | split: '[/email]' %}
<li class="widget-article">
<div class="widget-image">
<a href="{{ article.url }}">
<img src="{{ article.image | article_img_url: 'original' }}" alt="">
</a>
</div><!-- /.widget-image -->
<div class="widget-content">
<h3 class="widget-title">{{ article.title }}</h3><!-- /.widget-title -->
<p>
{% if content[1] %}
{{ content[1] | strip_html | truncatewords:15 }}
{% else %}
{{ content[0] | strip_html | truncatewords:15 }}
{% endif %}
</p>
</div><!-- /.widget-content -->
</li><!-- /.widget -->
{% endfor %}
Thanks
When you write "category" do you mean collection? Are you trying to associate a blog with a collection? If that's what you are trying to do then one way is to give the blog and collection the same handle.
then you could add your code to your collection template (I'd suggest as a snippet) and the snippet would start like:
{% assign blog = blogs[collection.handle] %}
{% if blog %}
<div class='blog-wrap'>...
{% for article in blog.articles %}
I'm trying to block customers tagged with "Wholesale" from the cart icon but it seems to block everybody. I've also tried to add this tag markup but won't let me add in {% include %} without giving me some type of error.
{% unless customer.tag contains 'Wholesale' %}
{% include
<li class="site-nav__item">
<a href="/cart" class="site-nav__link site-nav__link--icon cart-link js-drawer-open-right" aria-controls="CartDrawer">
<span class="icon-fallback-text">
<span class="icon icon-cart" aria-hidden="true"></span>
<span class="fallback-text">{{ 'layout.cart.title' | t }}</span>
</span>
<span class="cart-link__bubble{% if cart.item_count > 0 %} cart-link__bubble--visible{% endif %}"></span>
</a>
</li> %}
{% endunless %}
Your include usage is wrong. It is used to load only snippet files. Just remove {% include and it's corresponding %} and you're good to go.
Also it's customer.tags.
{% unless customer.tags contains 'Wholesale' %}
<li class="site-nav__item">
<a href="/cart" class="site-nav__link site-nav__link--icon cart-link js-drawer-open-right" aria-controls="CartDrawer">
<span class="icon-fallback-text">
<span class="icon icon-cart" aria-hidden="true"></span>
<span class="fallback-text">{{ 'layout.cart.title' | t }}</span>
</span>
<span class="cart-link__bubble {% if cart.item_count > 0 %} cart-link__bubble--visible{% endif %}"></span>
</a>
</li>
{% endunless %}
This should probably be a comment - but I need to include a code example...
As HymnZ has mentioned - customer.tags will only work if the customer is signed in.
If the customer is not signed in, they will be treated as a 'regular' customer.
If you want to hide the cart button until any type of customer is logged in - you'd need to wrap everything in an {% if customer %}
Then, if you wish to check if the customer is wholesale, you'd use
{% unless customer.tags contains 'Wholesale' %}
So to put it all together:
{% if customer %}
{% comment %} Customer is logged in. {% endcomment %}
{% unless customer.tags contains 'Wholesale' %}
<li class="site-nav__item">
<a href="/cart" class="site-nav__link site-nav__link--icon cart-link js-drawer-open-right" aria-controls="CartDrawer">
<span class="icon-fallback-text">
<span class="icon icon-cart" aria-hidden="true"></span>
<span class="fallback-text">{{ 'layout.cart.title' | t }}</span>
</span>
<span class="cart-link__bubble {% if cart.item_count > 0 %} cart-link__bubble--visible{% endif %}"></span>
</a>
</li>
{% endunless %}
{% endif %}
* Edit *
Following on from Gino's comment:
It seems there are some inconsistencies with how Shopify handles tags. My first thought was case sensitivity, however, I couldn't quite remember if tags were case sensitive.
So I logged into my store - and tried to add 'Test' and 'test'.
Once I had added 'Test' - it appeared as 'Test', but I couldn't add 'test' - as Shopify regarded 'Test' and 'test' as the same (case insensitive).
However, in the ui - it showed 'Test' (case sensitive) - which threw me into thinking it is case sensitive (it was nearly 3am when I answered)
A quick google, I found this post from Tobi Lutke - the chap who wrote Shopify https://ecommerce.shopify.com/c/shopify-discussion/t/tag-use-6631 - please see the last comment: "Tags are always downcased automatically." ......
So of course - if the tag is downcased automatically, and you're checking against the string 'Wholesale' it won't work.
OK, so I had asked a few weeks ago on the Shopify forum(slow responses) how to target just one product on a collection page so that there is no hover affect, but now I only want to target the frontpage collection and not my many other collection pages on the site.
Theme is Masonry and here is a snipet of the code I'm working with:
{% if settings.prod_block_display contains 'hover' %}
{% unless forloop.index == 1%}
<div class="hoverinfo{% if forloop.index == 1 %}no-overlay {% endif %}">
<a href="{{ product_url }}">
<div class="info-box">
<div class="title">{{ product-block.title }}</div>
<div class="price">
{% if product-block.compare_at_price_max > product-block.price %}
<span class="previously">{{ product-block.compare_at_price_max | money }}</span>
{% endif %}
{% if product-block.price_varies %}<span class="from">{{ 'products.listing.from' | t }}</span>{% endif %}
<span class="actual">{{ product-block.price | money }}</span>
</div>
</div>
</a>
</div>
{% endunless %}
{% endif %}
{% if settings.prod_block_qv and no_quick_buy == false %}
{% unless forloop.index == 1 %}
<div class="quick-buy-row{% if forloop.index == 1%}no-overlay {% endif %}">
{{ 'products.listing.quick_view' | t }}
</div>
{% endunless %}
{% endif %}
The "{% unless forloop.index == 1%}
" codes are the effects I only want to apply to the frontpage. Any help would be great!
You can add {{ collection.handle }} to classes of product divs where you want to apply the effect. Then in styles.css.liquid add a style for the collection handle (collection.handle) class as required.
What #HymnZ was trying to point to was that you can do things like in styles.liquid.css:
.frontpage .hoverinfo{
display:none;
}
and then in your template:
<div class="{{collection.handle}}">
<div class="hoverinfo">
...
</div>
</div>
This is the easiest way to use this strategy. What I was trying to add on was that you can potentially also use prefixes and suffixes on classes that concatenate with handles to offer more functionality. In styles:
.hide{
display:none;
}
.frontpage-show{
display:block;
}
and then in your template:
<div class="hide {{collection.handle}}-show">
Since most browsers support stacked selectors you probably don't need the -hide, -show variants but they can be helpful depending on how your mind works these things out. The sample above can be used to show/hide things for a variety of circumstances. e.g. you could target elements for a variety of collections:
.frontpage-show,
.collection1-show,
.frontpage.hide, /* these second two are the stacked equivalents to the -show variants */
.collection1.hide{
display:block;
}
Of course you can also do much of this in liquid itself:
{% assign showFor = "frontpage,collection1" |split ','%}
{% if showFor contains collection.handle %}
<div>Something limited</div>
{% endif %}
or
{% assign showFor = "frontpage,collection1" |split ','%}
<div class="{% if showFor contains collection.handle %}conditional{% endif %}">
Something limited
</div>
I'm trying to add the most popular products from my client's Shopify store on her home. So I heard what you do is create a collection (I called mine Most Popular) and then use the following code to display the products:
<div class="product span4">
{% assign best = collections["most-popular"] %}
<ul>
{% for product in best limit:10 %}
<li>{{ product.title }}</li>
{% endfor %}
</ul>
</div>
Simple, but didn't work. Just got a blank box with nothing in it. Anyone know the proper code for displaying items in my collection?
Just try this code it will call products from collection named Most Popular
<div class="product-sec">
<ul>
{% for product in collections.most_popular.products limit: 4 %} <!--/*********** most_popular is name under collections limit is uded to show no. of products ******/ -->
<li><img style="width:177px;height:177px;" src="{{ product.featured_image | product_img_url: 'medium' }}" alt=""></li>
{% endfor %}
</ul>
<span>Most Popular</span>
I hope it will help you