I'm building a Shopify app which offers additional products or services related to some identified products. In some cases, I end up adding a product to cart from cart page.
I found this question quite useful, to take actions on cart changes. The issue is that I'm currently forced to reload the page to re-render the cart along with the new product. I can't reasonably reconstruct the cart myself to include new items.
Hence, is there a way to trigger an "AJAX rendering" of the cart and avoid a full page reload ?
You can achieve this in many ways depending on your end goal. From your description, I have understood that you just want your script to run on Cart page. However, just note that a user may proceed to Checkout page without visiting Cart page. So just cover all your use cases.
This would have been much easier if you had to do this in theme and not in an app. Since, your app does not have any idea about the markup of Cart page, it is not easy to just append the new product row to existing table. As a workaround, on adding new product, call the cart page via Ajax, parse the returned HTML and replace the Cart form. So after adding new product, just call the below code to re render product form on Cart page.
function RerenderCart() {
$.get("/cart", function (data) {
const parser = new DOMParser();
const doc = parser.parseFromString(data, "text/html");
const formSelector = doc.querySelector("form[action='/cart']");
$("form[action='/cart']").replaceWith(formSelector);
});
}
Add checks for cart page and if form was found in returned HTML.
This code works fine on Debut Shopify theme. Just thoroughly test it on all your use cases.
DOMParser
Related
I'm trying to figure out how to implement the shopping cart functionality on a page using Vue.js. I get a list of items from an API call and print them on page load. But I'm stuck trying to add items to my cart. The functionality should include the ability to select a quantity of an item and add it to the cart by clicking the "add to cart" button. So it should allow, directly from the cart, to change quantities and remove items from the cart.
For this kind of situation, use a state management pattern like vuex (or pinia), and it will store your data after route change also.
For more clear context, go through this link:
https://vuex.vuejs.org/
I am writing a Shopify app and I would want to listen to the shopify cart update event. I know that when user clicks on remove or increase the item quantity. Shopify send a POST request to the backend to update the card. My app calculates the shipping value based on shopify cart item quantity. I add my app script to the shopify via script-tag.
I tried to listen to the quantity input but this event only fires one. I think shopify updates the input DOM after every cart update so it may remove my listener.
$('body').on('change', '.input[name="updates[]"]', function() { console.log('HELLO')});
How can I listen to the cart update event? It seems to be a simple question but I really cannot find any answer regarding to Shopify!
So there are 2 ways that a Shopify cart may get updated. Either via submitting form or using Ajax API. Assuming, you have already solved the form submission case by calling your calculate shipping function on page load. For Ajax based cart updates there is no standard event. Some themes may fire an event on cart update, but in case of a generic app, it is not possible to rely on them due to no defined standard behavior.
So what you can do is to listen to AJAX calls and call your function if it matches your conditions. Shopify Docs for Ajax API lists the 4 types of POST request that may update the Cart. So by patching the open function of XMLHttpRequest we add an event listener for load that fires when the request finished successfully. In the event callback, we check if the URL was the one used for updating cart, then call update shipping function.
const open = window.XMLHttpRequest.prototype.open;
function openReplacement() {
this.addEventListener("load", function () {
if (
[
"/cart/add.js",
"/cart/update.js",
"/cart/change.js",
"/cart/clear.js",
].includes(this._url)
) {
calculateShipping(this.response);
}
});
return open.apply(this, arguments);
}
window.XMLHttpRequest.prototype.open = openReplacement;
function calculateShipping(cartJson) {
console.log("calculate new shipping");
console.log(JSON.parse(cartJson));
}
Idea taken by answer from Nicolas
ajaxComplete was not used because it only listens to requests made using jQuery.
Passing response to your Shipping function saves the additional Get Cart Ajax call.
Update
If the above code does not work for you or does not catch all the calls, see my other answer that also listens to all Fetch API calls if that is being used to update cart.
Listen to Cart changes using Fetch API
To update item quantity fields in the cart in sectioned theme
Step 1: You access Shopify admin, click Online Store and go to Themes.
Step 2: Find the themes that you want to edit, then press Actions then Edit Code.
Step 3: Look at Sections, you click on cart-template.liquid. In case that you are not using the theme that does not have the address, you can access Template directory and click cart.liquid.
Step 4: Find the phrase written as update[item.id] in input tag.
Step 5: Change the name into the value of name= “updates[]”.
Step 6: Reiterate these aforementioned steps whenever you see an name value of updates[] in input tag.
Step 7: Click Save and you update item quantity fields successfully..
Currently, I am working on a Shopify app and I need to retrieve all products (featured collections) that are shown on the home page.
I tried {{product}}, {{collection.products}}
I have checked the Shopify cheat sheet but I can't find anything useful.
I can access products on the collection page and the home page using Shopify liquid.
Now I want to access products on the index page using Shopify liquid.
Please help me
Thank you
The solution to the above problem
I have used jquery to find the product handles using script tags, After finding the handle of all products that are displayed on the index (home) page.
I run the following ajax to get product details using product handle.
jQuery.ajax({
url: "/products/product-handle.js",
dataType: 'json',
async: false,
success: function(p) {
//after function success the data of every product is stored in p variable
}
})
Now I am able to do other calculations with product data.
I'm using Hotcakes Commerce DNN modules and I'd like to know how I can allow the user to stay on the product page after the "Add to Cart" button is clicked. The default behaviour is to redirect the user to the cart page whenever the a product is added to the cart.
The easiest way to make this happen is to modify your viewset to change how the add to cart buttons work. Here's a summary of the required steps:
Add and begin modifying your viewset if you haven't started already.
Modify your \VIEWSETNAME\Views\Products_ProductDetails.cshtml file to change the add to cart action from a post, to an AJAX link. This will allow you to add products to cart directly using a link, but keep you on the page.
If you're using the Mini Cart, refresh the page using JS so that it updates appropriately.
Please note that this option won't work well if your products have choices. If this is the case, you should instead allow your customers to be directed to the cart page, and use a parameter there to determine whether or not you redirect back to the product page.
is there an event which is triggered when the shopify cart has changed. I can refresh the cart every x seconds to see if something has changed but an event based approach is always better.
There isn't a one stop 'shopping' (he he) way to do it but it can be done.
In Shopify items are added to the cart either via a a regular HTML form POST to '/cart/add' or via Ajax so broadly speaking you'll need to account for both. Further, when using Ajax theme developers can either use the Shopify Ajax API or go for a straight up Ajax POST.
In the first case what you can do is add a submit handler to the form on page load so you'll be able to pick up the POST event just before the item is added.
In the second case where Ajax is being used via the Javascript wrapper API you can define a function which Shopify will call when the cart changes. E.g. suppose you defined this function:
Shopify.onCartUpdate = function(cart) {
alert('There are now ' + cart.item_count + ' items in the cart.');
};
The Ajax API will invoke it after items are added to the cart. You can check out the API sandbox to get a feel for it.
Finally there is the case where Ajax is being used directly. This the same scenario as this SO question and the accepted answer there where they work with the XMLHTTPRequest prototype methods look pretty good to me. If you are happy to use jQuery then using ajaxComplete would make it even simpler.
I am assuming you want to know when a customer's cart is changed which is technically on two basis :
there is cart created whenever first add to cart event happens
when a user completes a transaction and then the next time he/she visits the store and adds anything to their basket then a new cat is created.
When a cart is created an id is assigned to it and it has an expiration which is set in cookie with name "cart" this token is also delivered in webhook post callbacks as id and cart_token in carts_update and checkout event.
So to check to when a new cart is created you can do something like :
shopifyCart = function() {//call this on page load
var cartCookie = getCookie('cart');//Get shopify cart cookie
if( cartCookie !== undefined && cartCookie !== '' )
{
if( cartCookie !== getCookie('key') )//reference key
{
setCookie('key', cartCookie);//set cookie for next time comparison
//Do your action on the event
}
}
};
No. There is no native event broadcast when the cart changes. You are free as a bird to wire up your own listener to your own events. Since you can control what goes into the cart, you can thus control what happens on changes. The API is decent and there is plenty of free code kicking around in Prototype, Moo and jQuery to suit most devs taste.