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

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.

Related

Combine two customer inputs in shopify to one customer tag

How can i get this code to combine the information from the drop down and the customer input into a single customer tag?
<div class="relative">
<label for="SocialMediatype">Select a social media</label>
<select id="socialmediatype" name="customer[tags]">
<option>Discord</option>
<option>Reddit</option>
<option>Instagram</option>
</select>
</div>
<label for="SocialMediaUsername">Social Media Username</label>
<input type="text" name="customer[note]" id="socialuser" {% if socialuser %}value="{{ socialuser }}"{% endif %} >
{% assign social = socialmediatype.id %}
{% assign socialuser = socialmediatype.id %}
<input type="hidden" name="customer[tags]" id="socialName" value="{{social, socialuser}}" >

Add to cart form not adding items to cart

I'm trying to create buttons that add specific quantities of a product to the cart, so I modified the form that is automatically generated by the product page in Shopify, but it seems my code won't add any products from any of my 3 buttons to the cart page. I created 3 different IDs because each button posts the same product but a different quantity of that product. It also has a different description otherwise I would just leave it as 1 ID to keep it simple.
<form action="/cart/add" method="post" enctype="multipart/form-data" id="AddToCartForm">
{% for variant in product.variants %}
{% if variant.available %}
<option value="{{ variant.id }}">
{{ variant.title }} - {{ variant.price | money_with_currency }}
</option>
{% else %}
<option disabled="disabled">
{{ variant.title }} - sold out
</option>
{% endif %}
{% endfor %}
{{ current_variant.price | money }}
<input type="hidden" id="Quantity" name="quantity" value="1" min="1">
<input type="submit" class="two-cans" name="id" quantity="1" id="6556104458433" value="Get 2 Cans"/>
<input type="submit" class="four-cans" name="id" quantity="2" id="6556136014017" value="Get 4 Cans"/>
<input type="submit" class="six-cans" name="id" quantity="3" id="6556139389121" value="Get 6 Cans"/>
</form>
Adding the id attribute on a submit button will not do what you expect it to do, as it has nothing to do with the actual Shopify id of a product or a variant.
The quantity attribute does not do anything by itself, so that will not work either.
A typical add to cart form will look something like this:
<form method="post" action="/cart/add">
<input type="hidden" name="id" value="{{ product.variants.first.id }}" />
<input min="1" type="number" id="quantity" name="quantity" value="1"/>
<input type="submit" value="Add to cart" class="btn" />
</form>
For your specific use case, a good approach would be using JS instead of liquid. You can use Shopify's REST Api, start by replacing the submit inputs with simple buttons and moving them outside of the form:
<button class="custom-submit-button two-cans" name="id" quantity="2" id="6556104458433">Get 2 Cans</button>
<button class="custom-submit-button four-cans" name="id" quantity="4" id="6556136014017">Get 4 Cans</button>
<button class="custom-submit-button six-cans" name="id" quantity="6" id="6556139389121">Get 6 Cans</button>
Then adding a bit of jQuery to handle the requests:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
function addItemToCart(variant_id, qty) {
var data = {
"id": variant_id,
"quantity": qty
}
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: data,
dataType: 'json',
success: function() {
location.reload();
}
});
}
$('.custom-submit-button').click(function(){
addItemToCart($(this).attr("id"), $(this).attr("quantity"));
});
</script>

Console Error with new ShopifyOptionSelectors

I am trying to add the javascript code that allows me to have multiple product options following this shopify guide.
I have the included the needed file in the head of my theme.liquid:
{{ 'option_selection.js' | shopify_asset_url | script_tag }}
I have the following code in my product.liquid file:
<form action="/cart/add" method="post">
<div id="product-variants">
<div id="price-field"></div>
<select id="product-select" name="id">
{% for variant in product.variants %}
<option value="{{ variant.id }}"
>{{ variant.title }} - {{ variant.price | money }}</option
>
{% endfor %}
</select>
</div>
<input
type="button"
name="add"
value="Purchase"
id="purchase"
/>
</form>
<script type="text/javascript">
var selectCallback = function(variant, selector) {
if (variant) {
if (variant.available) {
// Selected a valid variant that is available.
console.log('available')
} else {
// Variant is sold out.
console.log('sold out')
}
// variant doesn't exist.
console.log('no variant')
}
}
// initialize multi selector for product
jQuery(function($) {
new Shopify.OptionSelectors("product-select", {
product: `{{ product | json}}`,
onVariantSelected: selectCallback,
enableHistoryState: true
});
});
</script>
I received the following error in my console:
Uncaught TypeError: Cannot read property 'length' of undefined
Im not too sure what i am doing wrong

Shopify variant swatches or radio buttons instead of dropdowns in Slate

Shopify's tutorial for color swatches isn't supported yet for Slate,
and the select callback referenced no longer exists in the code base. Is it possible to modify this tutorial to work on Slate themes to create radio buttons or swatches instead of a dropdown for selecting variants on the product template?
Yes. I was able to get this tutorial to work by modifying the code slightly. This workaround is only going to be relevant until the shopify tutorial is updated to correspond to Slate.
Follow the tutorial as per the directions.
When you get to the step "Locate your selectCallback function",
you will notice there is no selectCallback function in Slate. Yikes!
Instead find "_onSelectChange" in theme.js and add the code there.
This is the final function with the swatches code added:
/**
* Event handler for when a variant input changes.
*/
_onSelectChange: function() {
var variant = this._getVariantFromOptions();
this.$container.trigger({
type: 'variantChange',
variant: variant
});
if (!variant) {
return;
}
// BEGIN SWATCHES
var selector = this.originalSelectorId;
if (variant) {
var form = $(selector).closest('form');
for (var i=0,length=variant.options.length; i<length; i++) {
var radioButton = form.find('.swatch[data-option-index="' + i + '"] :radio[value="' + variant.options[i] +'"]');
if (radioButton.size()) {
radioButton.get(0).checked = true;
}
}
}
// END SWATCHES
this._updateMasterSelect(variant);
this._updateImages(variant);
this._updatePrice(variant);
this.currentVariant = variant;
if (this.enableHistoryState) {
this._updateHistoryState(variant);
}
},
Then, once you've completed the tutorial, you will notice it's still not working. This is because the code you add to theme.liquid uses a class that is no longer on your variant Selects.
On product.liquid (this is a Section on most Slate themes) Add the class "single-option-selector" to your selects, like so:
{% unless product.has_only_default_variant %}
{% for option in product.options_with_values %}
<div class="selector-wrapper js">
<label for="SingleOptionSelector-{{ forloop.index0 }}">
{{ option.name }}
</label>
<select
id="SingleOptionSelector-{{ forloop.index0 }}"
class="single-option-selector"
data-single-option-selector
data-index="option{{ option.position }}">
{% for value in option.values %}
<option value="{{ value | escape }}"
{% if option.selected_value == value %}selected="selected"{% endif %}>
{{ value }}
</option>
{% endfor %}
</select>
</div>
{% endfor %}
{% endunless %}
Now, the tutorial should work as it's supposed to. I hope this helps someone out!

How do i dynamically/evaluate via expression json property in django template

reading in a JSON for sport. using a partial for matchup markup.
awayteam and home team for most part share identical markup but the JSON properties which I have no control are such below:
<div class="away {{game.awayTeam_last_name|slugify}}">
<a href="#" title="{{game.awayTeam_first_name}} {{game.awayTeam_last_name}}">
<span class="{{league}}-logo"></span>
<span class="city">{{game.awayTeam_first_name}}</span>
{% if game.event_status != "pre-event" %}
<span title="score">{{game.awayTeam_score}}</span>
{% else %}
<span title="record entering game">(0-0)</span>
{% endif %}
</a>
</div>
<span>#</span>
<div class="home {{game.homeTeam_last_name|slugify}}">
<a href="#" title="{{game.homeTeam_first_name}} {{game.homeTeam_last_name}}">
<span class="{{league}}-logo"></span>
<span class="city">{{game.homeTeam_first_name}}</span>
{% if game.event_status != "pre-event" %}
<span title="score">{{game.homeTeam_score}}</span>
{% else %}
<span title="record entering game">(0-0)</span>
{% endif %}
</a>
</div>
is there a way to shrink/refactor the above like some expression valuator to make home and away passed via a variable.
didn't answer own question but i did get Data guys to better format the data, so became..
awayteam: { first_name:'', last_name:'', score:'' }
hometeam: { first_name:'', last_name:'', score:'' }
allowing me to shrink in half the template =)