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.
Related
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
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..
On a shopify PLUS store I'm trying to customize the checkout.liquid at the shipping method select page, so far so good, but my script only works after a refresh. This is probably due to the fact that my script runs before the shipping methods are all loaded :(
Is there any event I can listen for, that tells me all shippingmethods have been loaded?
I tried to use the shopify.onCartupdate event, because once the shipping methods are loaded the first one is applied to the checkout by default (added to the checkout total) but unfortunately, and maybe logicallly the checkout does not update the cart for the shipping method.
Any help would be appreciated.
Super late answer however you can use this new snippet.
Checkout.$(document).on('page:change', function() {
// ...
});
Inside the call back function you can run any code, or use window.location to determine which page you're on specifically. Needs to be run on checkout.liquid meaning Plus stores only.
Shipping methods are always loaded AFTER your checkout.liquid renders. So you cannot affect them. Whatever you are trying to do, you will have to monkey patch in Javascript world. And even then, good luck. I am not sure there is even an event you can subscribe to labelled shippingMethodsReady kind of thing.
I'm in Registration.vue component. The component contains registration form with email, password, etc.. fields.
I would like to thanks user for successful registering (with instruction that he should go check email).
What is the best solution to do this?
I was thinking about:
redirecting to second component using this.$router.push or this.$router.replace but this will change URL and when somebody go this URL without registering he will see message that he should check email...
replacing current component with other when registering action successful but I dont know how to do this (without URL change, and with good code).
using <component v-bind:is="currentView"> but I am not sure if this is best solution. I need to make three files (for parent component with :is, for form and for thanks). Also i need to emit event from child that registration went well, but on the other hand i should fire vuex registration action and dont expect for response (see the next sequence)
The other thing is that we should not wait for the vuex action to be completed, but i need to know if registration went well - https://github.com/vuejs/vuex/issues/46#issuecomment-174539828
I am using vue.js 2, vue-router, vuex
Thanks
You could use something like Sweet Alert to display a success or error dialog. It supports Ajax requests so you can display a "your registration is processing, please check your email" message while it is being handled.
The first approach is suitable when user successfully registers and then redirected to login page.
Now issue how to check whether user has entered required field? So there comes form validations. You can use vee-validate plugin and it's perfect for all projects. I am using it and it has so many available validations.
With these UI validations, after they are passed successfully then only submit action will be fired or else user will be prompted for entering required field.
You can see basic example here - http://vee-validate.logaretm.com/index.html#basic-example
When action is performed,
///main.js
...
Vue.use(VeeValidate)
...
// register.vue
this.$validator.validateAll().then((result) => {
if (result) {
//done
this.$router.replace( '/login' );
}
else{
// throw error
}
Simple as that.
Try this approach if you want the UI validations on the form.
Let me start to say that I am new to Magento.
I am building a small extension that automatically injects relevant youtube videos to product pages (electronics, books, etc...) and I need to know if the user clicked the 'Add to Cart' button.
Is it possible to know when a user adds a product to the cart via an API call? Other method? Thanks in advance.
You have to write event observer for your custom extension and need to track that when add to cart event is fired you can run your own logic inside this observer.
<events>
<checkout_cart_product_add_after>
<observers>
<uniquetag>
<type>singleton</type>
<class>vendor_module_model_observer</class>
<method>updatepriceing</method>
</uniquetag>
</observers>
</checkout_cart_product_add_after>
</events>
However this is not full proof solution but this is what how you can achieve your intended task.
Good luck