when i click on add to cart button, page refreshes and then product is added how can i do this without getting the page refreshing - shopify

i added the button on product page below each product but they are refreshing the page i tried this code but whenever i click on add to cart page refreshes, how can it be done without refreshing the page and product still get added to cart without refreshing and redirecting to other page
<div class="buy-now-bx">
{% if card_product.available %}
<form method="post" action="/cart/add">
<input type="hidden" name="id" value="{{ card_product.selected_or_first_available_variant.id }}">
<div style="display: flex">
<input type="hidden" name="return_to" value="back" />
<input type = "submit" value = "Add to Cart" name = "addbutn" id="addbutn" class="button buynow-btn" data-id="{{ card_product.variants.first.id }}"/>
</div>
</form>
{% else %}
<a class="button buynow-btn" tabindex="0" href="{{ card_product.url | default: '#' }}">Sold out</a>
{%- endif -%}
</div>

To add an add-to-cart button to a Shopify product page without causing a page refresh, you can use Shopify's AJAX API to perform an AJAX request to the Shopify cart API. This allows you to add products to the cart without a page refresh.
Here's an example code snippet that you can use to achieve this:
In your product.liquid file, add a button to trigger the AJAX request when clicked:
<div class="buy-now-bx">
{% if card_product.available %}
<form method="post" action="/cart/add" id="add-to-cart-form">
<input type="hidden" name="id" value="{{ card_product.selected_or_first_available_variant.id }}">
<div style="display: flex">
<input type="hidden" name="return_to" value="back" />
<button type="submit" class="button buynow-btn" data-id="{{ card_product.variants.first.id }}" id="add-to-cart-btn">Add to Cart</button>
</div>
</form>
{% else %}
<a class="button buynow-btn" tabindex="0" href="{{ card_product.url | default: '#' }}">Sold out</a>
{% endif %}
</div>
Add the following code to your theme.js file or create a new file with the following code:
$(document).ready(function() {
$('#add-to-cart-form').submit(function(event) {
event.preventDefault(); // prevent the default form submit behavior
var form = $(this);
var addToCartButton = form.find('#add-to-cart-btn');
var originalButtonText = addToCartButton.text();
addToCartButton.attr('disabled', true).text('Adding...'); // disable the button and change the text
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: form.serialize(),
dataType: 'json',
success: function() {
addToCartButton.text('Added!'); // change the button text
setTimeout(function() {
addToCartButton.attr('disabled', false).text(originalButtonText); // re-enable the button and change the text back to the original text after a delay
}, 1000);
},
error: function() {
addToCartButton.text('Error'); // handle the error by changing the button text
}
});
});
});
This code will handle the form submit event and send an AJAX request to the Shopify cart API when the add-to-cart button is clicked. It will also disable the button and change the text to indicate that the product is being added to the cart. Once the request is complete, it will change the button text to "Added!" and then change it back to the original text after a delay.

Related

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>

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.

Adding an "ADD TO CART" button to a collection

I have a client asking to add an "ADD TO CART" button under each product in their collections and I can't figure out how.
I'm new to the Shopify platform and I am not familiar with Liquid but I did try to use the built in "Channel" of adding a Buy Button, but when trying to paste in the code it didn't populate anything in the preview page.
Any help would be wonderful.
Use the shopify API by adding this into the collection.liquid
<form method="post" action="/cart/add">
<input type="hidden" name="id" value="{{ product.variant.id }}" />
<input min="1" type="number" id="quantity" name="quantity" value="1"/>
<input type="submit" value="Buy" class="btn" />
</form>
Add that somewhere in this loop
{% for product in collection.products %}
...
{% endfor %}
product.variant.id identifies which item is added to the cart and it could be replaced with product.variants.first.id
This details how it works and applies to standard, non ajax, forms too
https://help.shopify.com/en/themes/development/getting-started/using-ajax-api#add-to-cart

Shopify PLUS - additional checkout custom field

I was trying to add additional custom field in the checkout screen and here is my code:
<div class="additional-checkout-fields" style="display:none">
<div class="fieldset fieldset--address-type" data-additional-fields>
<div class="field field--optional field--address-type">
<h2 class="additional-field-title">ADDRESS TYPE</h2>
<div class="field__input-wrapper">
<label>
<input data-backup="Residential" class="input-checkbox" aria-labelledby="error-for-address_type" type="checkbox" name="checkout[Residential]" id="checkout_attributes_Residential" value="Residential" />
<span>Residential</span>
</label>
<label>
<input data-backup="Commercial" class="input-checkbox" aria-labelledby="error-for-address_type" type="checkbox" name="checkout[Commercial]" id="checkout_attributes_Commercial" value="Commercial" />
<span>Commercial</span>
</label>
</div>
</div>
</div>
</div>
<script type="text/javascript">
if (window.jQuery) {
jquery = window.jQuery;
} else if (window.Checkout && window.Checkout.$) {
jquery = window.Checkout.$;
}
jquery(function() {
if (jquery('.section--shipping-address .section__content').length) {
var addType = jquery('.additional-checkout-fields').html();
jquery('.section--shipping-address .section__content').append(addType);
}
});
</script>
It returns the checkout page like this -
The problem is - once I click continue button and comes back to this page again, I don't see the checkbox checked. I feel the values are not being passed or may be something else.
What am I missing?
From the usecase, it looks like you want the user to select the Address Type either Residential or Commercial so a raido button group seems more suitable. I have edited the HTML to create the Radio Button instead of Checkbox. To maintain the state, I have used Session Storage. You may also replace Session Storage with Local Storage if you want to do so. For explanation check code comments.
<div class="additional-checkout-fields" style="display:none">
<div class="fieldset fieldset--address-type" data-additional-fields>
<div class="field field--optional field--address-type">
<h2 class="additional-field-title">ADDRESS TYPE</h2>
<div class="field__input-wrapper">
<label>
<input class="input-radio" aria-label="" type="radio" name="checkout[address_type]" id="checkout_attributes_Residential" value="residential" checked>
<span>Residential</span>
</label>
<label>
<input class="input-radio" aria-label="" type="radio"name="checkout[address_type]" id="checkout_attributes_Commercial" value="commercial">
<span>Commercial</span>
</label>
</div>
</div>
</div>
</div>
JavaScript part
<script type = "text/javascript" >
if (window.jQuery) {
jquery = window.jQuery;
} else if (window.Checkout && window.Checkout.$) {
jquery = window.Checkout.$;
}
jquery(function() {
if (jquery('.section--shipping-address .section__content').length) {
var addType = jquery('.additional-checkout-fields').html();
jquery('.section--shipping-address .section__content').append(addType);
// Get saved data from sessionStorage
let savedAddressType = sessionStorage.getItem('address_type');
// if some value exist in sessionStorage
if (savedAddressType !== null) {
jquery('input[name="checkout[address_type]"][value=' + savedAddressType + ']').prop("checked", true);
}
// Listen to change event on radio button
jquery('input[name="checkout[address_type]"]').change(function() {
if (this.value !== savedAddressType) {
savedAddressType = this.value;
sessionStorage.setItem('address_type', savedAddressType);
}
});
}
});
</script>
You are responsible for managing the state of your added elements. Shopify could care a less about stuff you add, so of course when you flip around between screens, it will be up to you to manage the contents. Use localStorage or a cookie. Works wonders. As a bonus exercise, ensure that your custom field values are assigned to the order when you finish a checkout. You might find all your hard work is for nothing as those value languish in la-la land unless you explicitly add them as order notes or attributes.

In bootstrap form, how to connect "submit" button to database?

I recently started to use this bootstrap_form from django_bootstrap3 package. It's a nightmare... Here is a simplified version of what I want to do:
- I have 2 textboxes for user to enter data
- POST the data to a local database through clicking a "submit" button
What I had originally was to have a base_form.html file that store the form such as:
{% extends "expense/base.html" %}
{% block content %}
<form method="post">
{% csrf_token %}
<input id="field1" type="text" name="field1" value="{{ field1 }}">
<input id="field2" type="number" name="field2" value="{{ field2 }}">
<input id="submit" type="submit" value="Submit">
</form>
Then I would just call this form in my base.html, everything works, just ugly. Now that I started to use django_bootstrap3 package, it's great looking, less code, just nothing works. With django_bootstrap3, I no longer need the base_form.html (it grabs data from forms.py directly), instead I just need to call {% bootstrap_form form %} like the following:
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary btn-lg btn-block" data-loading-text="Loading...">
{% bootstrap_icon "star" %} Submit
</button>
{% endbuttons %}
However, there is no place for me to say this is a form POST not GET. Also, there is no place for me to say these are all input field, and submit button should actually submit. Right now the behavior is that after I write some data to the field, and click submit button, nothing is posting to the database. The submit button doesn't work at all.
I don't know what I am missing here. I am very new to web development using django and bootstrap framework. Please help.