Shopify - extract collection information - shopify

I am trying to write a shopify section that allows the selection of Collections in the Customise page. I am struggling to understand how to extract the collection information for use in the section's liquid file.
I have read the docs, and tried lot's of different snippets that I have found peppered over the internet, but nothing actually seems to pull the info.
Below is what I currently have
The p tags are me just seeing if there was any output at all, and there is not.
The for loop seems to be working as, for the number of collections selected, I get a list item (yay I guess?) - but that's as much magic as I could muster.
<div data-section-id="{{ section.id }}" >
<div class="flex-wrapper ignite-collection">
<ul>
{%- for block in section.blocks -%}
<li>
<a href="{{ collection.url }}">
<img src="{{ collection.image | img_url: '350x' }}" alt="{{collection.title}}">
<h4 class="flex-collection-heading">{{ collection.title }}TEXT HEADING</h4>
</a>
// all of these p tags are left overs from me trying variations of getting info
<p>collection.image {{collections['flex-collection'].image}}</p>
<p>collection.image.url {{ collections['flex-collections'].image.url }}</p>
<p>{{ collections.flex-collection.image.url }}</p>
<p>{{ collections[settings.flex-collection].url }}</p>
<p>collection.url {{settings.flex-collection.url}}</p>
</li>
{%- endfor -%}
</ul>
</div>
</div>
{% schema %}
{
"name": "Ignite Collection list",
"class": "ignite-collection-list-section",
"max_blocks": 6,
"settings": [
{
"type": "select",
"id": "justify-content",
"label": "Justify Content",
"options": [
{"value": "flex-start", "label":"Flex Start"},
{"value": "flex-end", "label":"Flex End"},
{"value": "center", "label":"Center"},
{"value": "space-between","label":"Space Between"},
{"value": "space-around","label":"Space Around"},
{"value": "space-evenly","label":"Space Evenly"}
]
}
],
"presets": [
{
"name": "Ignite Collection list",
"category": "Collections",
"blocks": [
{
"type": "collection"
},
{
"type": "collection"
}
]
}
],
"blocks": [
{
"type": "collection",
"name": "Collection",
"settings": [
{
"id": "flex-collection",
"type": "collection",
"label": "Collection"
}
]
}
]
}
{% endschema %}

Inside the for loop, you are using a liquid variable collection which has not been assigned. You need to add as the first line of the for loop something like {% assign collection = collections[block.settings.flex-collection] %}
Tip: you can output the collection as a JSON object to check that the correct assignment was made with something like:
<script>
console.log({{ collection | json }});
</script>
To check the json object use the javascript console in the Chrome devTools (F12) -> console.
The liquid variable collection after the assignment will reference the corresponding collection object so you need to modify the way you access the fields, say for example you want to output the collection title, you can do: <span>{{ collection.title }}</span>.
You will have to change the following in your code:
{%- for block in section.blocks -%}
{% unless block.settings.flex-collection %}
{% continue %}
{% endunless %}
{% assign collection = collections[block.settings.flex-collection] %}
<li>
<a href="{{ collection.url }}">
<img src="{{ collection.image | img_url: '350x' }}"
alt="{{collection.title}}">
<h4 class="flex-collection-heading">{{ collection.title }}TEXT HEADING</h4>
</a>
// all of these p tags are left overs from me trying variations of getting info
<p>collection.image {{ collection.image }}</p>
<p>collection.image.url {{ collection.image.url }}</p>
<p>collection.url {{ collection.url }}</p>
</li>
{%- endfor -%}
Using a variable is more efficient than looking for the collection object of interest every time you need to access a field of the collection.
Also, you want to skip the current iteration of the for loop if the collection was not set in the block (from the customizer), to do so you can add as the first line of the for loop the following:
{% unless block.settings.flex-collection %}
{% continue %}
{% endunless %}

Related

Shopify 'Page' Block Duplicating On All Blocks

I have an issue with a block I am editing for a client of mine in which they want to have a page popup within a section. The page selection is working great, styling is looking great however the selected page is duplicating across all the blocks within the section.
For example, the section itself is called 'Slideshow With Text', this section has blocks which contain an image, some text, a button and now this page popup and it just scrolls through each block. When I add a page to the first block, it works exactly how intended. However, when I add a page to the second block, it ignores my chosen page and uses the page selected in the first block.
Here is my code for reference:
Schema - last setting in block.
{
"type": "page",
"id": "page_popup",
"label": "Page Popup"
},
{
"type": "text",
"id": "page_popup_text",
"label": "Page Popup Text",
"default": "Page Pop Up Text"
}
Liquid - to display block within the other block elements.
{% if block.settings.page_popup != blank %}
<div>
{{ block.settings.page_popup_text }} {% render 'icon', name: 'right-caret' %}
<div class="page-popup" id="pagepopup">
<div class="page-popup-wrap content container {% if settings.table_styles_enabled %} table is-striped is-bordered {% endif %}">
<div class="one-whole column">
<h5 class="center">{{ pages[block.settings.page_popup].title }}</h5>
<div class="feature_divider"></div>
{{ pages[block.settings.page_popup].content }}
</div>
</div>
</div>
</div>
{% endif %}
I'm presuming I am getting this issue as 'page_popup' is storing for the entire section and not on a per block basis however, I'm not sure how to separate this.
Any ideas would be appreciated.
Luke

Is it possible to have the same section repeated in the same template?

Is it possible to have the same section repeated in the same template? If so, how?
template:
{% section 'two_images' %}
{% section 'two_images' %}
two_images:
<section data-aos="fade">
<div class="flex-images">
<img src="{{ section.settings.img1 | img_url: "3979x943" }}">
<img src="{{ section.settings.img2 | img_url: "3990x943" }}">
</div>
</section>
{% schema %}
{
"name": "Two Images",
"settings": [
{
"type": "image_picker",
"id": "img1",
"label": "First Image",
"info": "Recommended sizes: 3979x943"
},
{
"type": "image_picker",
"id": "img2",
"label": "Second Image",
"info": "Recommended sizes: 3990x943"
}]
}
{% endschema %}
The sections are showing but same pictures for both. I'm guessing it has to do something with "id"? Since it's repeated twice. What's the work around?
Right, so you cannot simply duplicate sections and expect them to have different content. Sections contains unique settings for each one of them, so you would need to create another section in "/sections" folder, lets say "two_images_2", and put same content there. Then you can include it in your template.
If the html content for both sections is exactly the same, you can create snippet with this html and include it in both sections, to avoid duplicating same html over and over again. Please note this does not applies to {% schema %}, as content of this tag is required in sections, so this will need to be duplicated
Hope this answer will clarify the logic behind sections for you,
Thanks

Shopify Palo Alto Theme; Attempting to include an 'Add To Cart' in product-grid-item

I know that Timber/Palo Alto is no longer supported but I am working on an old account that uses it and am not familiar with the theme.
I have been able to create a button that adds an item to a cart but after clicking add to cart it redirects to the cart page, I just want to add the item and allow the user to still browse the collection.
Any suggestions will be helpful, Thank you in advance
<!-- /snippets/product-grid-item.liquid -->
<form action="/cart/add" data-productid="{{product.id}}" method="post" enctype="multipart/form-data" id="AddToCartForm--{{section.id}}">
<div class = "variants-wrapper">
{% if variants_count > 1 %}
<select name="id" data-productid="{{product.id}}" id="productSelect--{{section.id}}" class="product-single__variants">
{% for variant in product.variants %}
{% if variant.available %}
<option {% if variant == product.selected_or_first_available_variant %} selected="selected" {% endif %} data-sku="{{ variant.sku }}" value="{{ variant.id }}">{{ variant.title }} - {{ variant.price | money_with_currency }}</option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - {{ 'products.product.sold_out' | t }}
</option>
{% endif %}
{% endfor %}
</select>
{% else %}
<input name="id" data-productid="{{product.id}}" type="hidden" value="{{ product.variants[0].id }}">
{% endif %}
{% if sold_out %}
<input type="hidden" type="text" id="Quantity1" name="quantity" value="0" min="0" class="quantity-selector quantity-input">
<a class="btn" href="{{ product.url | within: collection }}">{{ 'products.product.view_item' | t }}</a>
{% else %}
<div class="qtydiv">
<input type="text" id="Quantity1" name="quantity" value="1" min="1" class="quantity-selector quantity-input">
</div>
<button type="submit" name="add" id="AddToCart" class="btn" style="display: inline">
<span id="AddToCartText">{{ 'products.product.add_to_cart' | t }}</span>
</button>
{% endif %}
</div>
</form>
ajax-cart.js.liquid
ShopifyAPI.addItemFromForm = function(form, callback, errorCallback) {
var params = {
type: 'POST',
url: '/cart/add.js',
data: jQuery(form).serialize(),
dataType: 'json',
success: function(line_item) {
if ((typeof callback) === 'function') {
callback(line_item, form);
}
else {
ShopifyAPI.onItemAdded(line_item, form);
}
},
error: function(XMLHttpRequest, textStatus) {
if ((typeof errorCallback) === 'function') {
errorCallback(XMLHttpRequest, textStatus);
}
else {
ShopifyAPI.onError(XMLHttpRequest, textStatus);
}
}
};
jQuery.ajax(params);
};
This redirects to cart page, because that is how form action value is defined. So if you want to add it without page redirect and reload, use Shopify AJAX API that allows you manage CRUD operations on cart. Shopify AJAX API.
In the above scenario, you need to have a look at Add to Cart functionality.
Post Data
{
quantity: 2,
id: 794864229
}
Sample Code
// Send a seralized form
jQuery.post('/cart/add.js', $('form[action="/cart/add"]').serialize());
// or construct post data
jQuery.post('/cart/add.js', {
quantity: 1,
id: 794864229,
properties: {
'First name': 'Caroline'
}
});
Another approach that is a bit easy to implement is to use CartJS
So using data API, it would just be
<button data-cart-add="12345678">Add Product</button>
Sample implementation on Timber Shopify theme
in theme.liquid after timber.js load CartJS
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/shopify-cartjs/0.4.1/cart.min.js"></script>
Then below that in the jQuery ready function, initialize CartJS
CartJS.init({{ cart | json }}, {
"dataAPI": true
});
The add this code in product-grid-item.liquid
<button data-cart-add="{{ product.variants.first.id }}">Add Product</button>
This is working on my test installation of Timber theme.

Shopify 'view collection' button in featured collection

I'm theming the basic stuff for a webshop and trying to add a 'view collection'-button to the featured collection on the home page. In the documentation it states that normally I just need to do collection.url and get the url. But it doesn't seem to work. Can someone say what I do wrong?
(https://help.shopify.com/themes/liquid/objects/collection#collection-url)
{% if section.settings.show_view_all %}
<hr class="hr--clear">
<div class="text-center">
<a href="{{ section.settings.featured_collection.url }}" class="btn">
{{ 'collections.general.view_all' | t }}
</a>
</div>
{% endif %}
</div>
{% schema %}
{
"name": "Featured collection",
"class": "index-section",
"settings": [
{
"type": "text",
"id": "title",
"label": "Heading",
"default": "Featured collection"
},
{
"type": "collection",
"id": "featured_collection",
"label": "Collection"
},
I wrapped the h2 tag like this:
{% if section.settings.title != blank %}
<h2 class="small--text-center">{{ section.settings.title | escape }}</h2>
{% endif %}
As I do not ever plan to make the collection slug different, this works for me. Your mileage may vary. This is using the 'Simple' theme.
You should check the collection setting type:
https://help.shopify.com/themes/development/theme-editor/settings-schema#collection:
The output of the option the merchant selects from the drop-down is the handle of the collection.
So, instead of:
{{ section.settings.featured_collection.url }}
you should use:
{{ collections[section.settings.featured_collection].url }}

How can I add an editable static section to Shopify?

I’ve been playing around with Shopify’s sections feature. I thought I’d start simple, with a two field static section, to let admins edit the content of a help modal.
I read all the documentation I could find (not a whole lot), and “borrowed” some code from the Debut theme’s header section.
I have created a section file called help.liquid, and called it on my home page using {% section ‘help’ %}
The content is outputting on the page as expected, and the Help section is visible in the Sections tab of the admin system, but is uneducable. There must be something I’m missing, but I can’t work out what it is!
The code in my section file is as follows:
<div data-section-id="{{ section.id }}" data-section-type="help-section">
<div class="modal modal--help">
<div class="modal__hd">
<h2 class="modal__title">{{ section.settings.help_title }}</h2>
</div>
<div class="modal__bd">
{{ section.settings.help_content }}
</div>
</div>
</div>
{% schema %}
{
"name": "Help",
"settings": [
{
"type": "text",
"id": "help_title",
"label": "Help title",
"default": "Help"
},
{
"type": "text",
"id": "help_content",
"label": "Help content",
"default": "Here's some info on getting help"
}
]
}
{% endschema %}