I'm new to Ajax implementation and data-mage-init implementations in Magento 2.
So what I'm trying to do :
Situation now
When you are in your cart -> URL/checkout/cart/ you need to press the update button in order to update the QTY's in your cart. But since the cart does not remember the quantity's when you have 1 that exceeded current stock and it resets all fields i want to do something to fix that
Requested scenario
So i want to have the Qty in the cart updated when you change the qty itself and not have it updated in bulk with 1 button.
Code right now
So i have my JQuery (to perform the ajax) and pthml fille loaded like this : (module name = Designit/LiveUpdate)
app/code/Designit/LiveUpdate/view/frontend/layout/checkout_cart_index.xml
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<link src="Designit_LiveUpdate::js/LiveUpdate.js"/>
</head>
<referenceBlock name="checkout.cart.form">
<action method="setTemplate">
<argument name="template" xsi:type="string">Designit_LiveUpdate::cart/form.phtml</argument>
</action>
</referenceBlock>
</page>
I made some minor changes to the .pthml like giving the button that does the update right now an ID submitbutton. I thought is was handy to have control over the .phtml fille since that is where i want to get the data. Nothing special done there so i'm not posting that long code block unless requested.
Now i want to have Ajaxto validate this on each change in the input.qty field.
Js:
require(['jquery'], function ($) {
$("#submitbutton").hide();
var form = $('form#form-validate');
var qtyfields = $('input.qty');
form.find(qtyfields).each(function () {
console.log("test find fields");
$(this).change(function () {
console.log("test");
$.ajax({
type: "POST",
url: form.attr('action'),
data: form.serialize(),
success: function (response) {
// Here goes the validation ??;
}
});
});
})
});
You can see i have 2 'test' console logs there. One to see if it finds all the QTY fields and one to see if it can detect the change.
What i noticed so far :
- It does give me 6 console logs on page load for each qty field
- It does not give me console logs on change for some reason
- Not sure if my
url: form.attr('action')is a good choice here
Question
- How can i display the error when the qty field has changed to see live if it is in stock or not? And maybe even output the max stock available.
I thank everyone in advance who wants to put time into this question really really much!
Update
I have managed to have the quantity updated in the cart (not the error message) on change by doing this (do not mind the console.log because those are just for testing):
require(['jquery', 'Magento_Customer/js/customer-data',
'jquery/jquery-storageapi'], function ($) {
// $("#submitbutton").hide();
var form = $('form#form-validate');
var qtyfields = $('input.qty');
$('.page.messages').each(function () {
var thismessage = $(this);
thismessage.attr('id', 'messages');
});
form.find(qtyfields).each(function (e) {
var thisfield = $(this);
$(this).change(function () {
console.log('change detected');
form.submit();
});
});
form.on('submit', function (e) {
e.preventDefault();
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
success: function (res) {
},
error: function () {
console.log('error');
}
});
console.log('form submitted');
});
});
I still need a way to update the error messages.
Update
This is a better way. Still finding a way to update the Shipment calculation
define([
'jquery',
'Magento_Checkout/js/action/get-totals',
'jquery/ui'
], function (,ドル getTotalsAction) {
"use strict";
$.widget('mage.liveupdate', {
options: {
enabled: true,
qtyfield: 'input.qty',
form : 'form#form-validate'
},
_create: function () {
if (this.options.enabled) {
this._bindqtycart();
}
},
_bindqtycart: function () {
$("#submitbutton").hide();
var form = $(this.options.form);
var qtyfields = $(this.options.qtyfield);
form.find(qtyfields).each(function (e) {
$(this).change(function () {
form.submit();
});
});
form.on('submit', function (e) {
// var thisfield = $(this);
// var thisiteminfo = thisfield.closest(".item-info");
// var thissubtotal = thisiteminfo.children(".subtotal");
// var formsubtotals = $(this).find('.subtotal');
e.preventDefault();
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
success: function (response) {
var deferred = $.Deferred();
getTotalsAction([], deferred);
$('.cart.item').each(function () {
var thiscartitem = $(this);
var subtotal = thiscartitem.find('.subtotal');
var subtotalval = subtotal.find('span.price');
var qty = thiscartitem.find('.qty');
var qtyval = qty.find('input.qty').val();
var price = thiscartitem.find('td.price');
var priceval = price.find('span.price').html();
var priceval = priceval.replace('€ ' , '');
var priceval = priceval.replace(',' , '.');
var subtotalafter = qtyval*priceval;
subtotalval.html('€ ' + (subtotalafter.toFixed(2)));
})
}
});
});
}
});
return $.mage.quantity;
});
-
How you updated Cart summary with this? Can you please post it here?Magecode– Magecode2017年08月30日 06:43:31 +00:00Commented Aug 30, 2017 at 6:43
-
I have added this as an answer. This is what i worked with and its currently running on a live websiteCompactCode– CompactCode2017年08月31日 00:31:56 +00:00Commented Aug 31, 2017 at 0:31
2 Answers 2
Just a quick update. I finished this by using regular expression.I still think if we only get the JSON formatted data for the quote data from the controller than that should be better for performance. Thank you.
Solution:
require(['jquery', 'Magento_Customer/js/customer-data',
'jquery/jquery-storageapi'], function ($) {
// $("#submitbutton").hide();
var spinner = $('.ajax-checkout-cart-loader');
var form = $('form#form-validate');
var qtyfields = $('#cart-<?php echo $_item->getId() ?>-qty');
var changeDected = 0;
$('.page.messages').each(function () {
var thismessage = $(this);
thismessage.attr('id', 'messages');
});
/*
form.find(qtyfields).each(function (e) {
var thisfield = $(this);
//console.log(thisfield);
$(this).change(function () {
spinner.css("display", "block");
console.log('change detected');
form.submit();
});
});
*/
form.on('submit', function (e) {
e.preventDefault();
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
success: function (response) {
var parsedResponse = $.parseHTML(response);
var itemSubtotal = $(parsedResponse).find(".ajax-subtotal").text();
var itemSubtotalArray = itemSubtotal.split(" ");
if(itemSubtotalArray.length !== 1) {
itemSubtotalArray = itemSubtotalArray.filter(s => s.replace(/\s+/g, '').length !== 0);
//console.log(itemSubtotalArray);
} else {
location.reload();
}
//console.log(itemSubtotalArray.length);
var ajaxSubtototal = $('.ajax-subtotal');
for (i=0; i <= itemSubtotalArray.length - 1; i++) {
ajaxSubtototal.eq(i).find('span.price').text(itemSubtotalArray[i]);
}
var quoteDataRegexp = /\"quoteData\":(.*)/;
var quoteDataMatch = quoteDataRegexp.exec(response);
var grandTotalRegexp = /\"grand_total\":\"(.*?)\",/;
var subTotalRegexp = /\"subtotal\":\"(.*?)\",/;
var taxRegexp = /\"tax_amount\":\"(.*?)\",/;
var cadRegexp = /\"Discount \(CAD Discount\)\",\"value\":\"(.*?)\",/;
var grandTotalMatch = grandTotalRegexp.exec(quoteDataMatch[1]);
var subTotalMatch = subTotalRegexp.exec(quoteDataMatch[1]);
var taxMatch = taxRegexp.exec(quoteDataMatch[1]);
var cadDiscountMatch = cadRegexp.exec(quoteDataMatch[1]);
/* subtotal for each item in the table */
/* data set for the Knockout data bar */
//var total = checkoutConfig2.match(/\"row_total_incl_tax\"/).text();
var grandTotal = parseFloat(Math.round(grandTotalMatch[1] * 100) / 100).toFixed(2);
var subTotalbar = parseFloat(Math.round(subTotalMatch[1] * 100) / 100).toFixed(2);
var taxTotal = parseFloat(Math.round(taxMatch[1] * 100) / 100).toFixed(2);
var discountTotal = parseFloat(Math.round(cadDiscountMatch[1] * 100) / -100).toFixed(2);
//console.log(grandTotal);
$('.totals.sub').find('span.price').text("$" + subTotalbar);
$('.totals-tax').find('span.price').text("$" + taxTotal);
$('.grand.totals').find('span.price').text("$" + grandTotal);
$('.totals:nth-child(2)').find('span.price').text("-$" + discountTotal);
spinner.css("display", "none");
//location.reload();
},
error: function () {
console.log('error');
}
});
//console.log('form submitted');
});
});
-
I have updated my start post to show a better wayCompactCode– CompactCode2017年12月06日 23:13:29 +00:00Commented Dec 6, 2017 at 23:13
-
NOT WORKING with the Minimum Qty Allowed validation (e.g - Bundle Product with min qty 5)Vishal Thakur– Vishal Thakur2022年03月28日 13:34:28 +00:00Commented Mar 28, 2022 at 13:34
So the total solution that i worked with is like this :
This includes updated cart summary's
require(['jquery', 'Magento_Customer/js/customer-data',
'jquery/jquery-storageapi'], function ($) {
$("#submitbutton").hide();
var form = $('form#form-validate');
var qtyfields = $('input.qty');
form.find(qtyfields).each(function (e) {
$(this).change(function () {
form.submit();
});
});
form.on('submit', function (e) {
var thisfield = $(this);
var thisiteminfo = thisfield.closest(".item-info");
var thissubtotal = thisiteminfo.children(".subtotal");
var formsubtotals = $(this).find('.subtotal');
e.preventDefault();
$.ajax({
url: form.attr('action'),
data: form.serialize(),
type: 'post',
success: function (response) {
var data = jQuery.parseJSON(response);
var subtotal = data.subtotal_with_discount;
var grandtotal = data.grand_total;
var shipping = data.shipping_amount;
var tax = grandtotal - shipping - subtotal;
$('.totals.sub').find('span.price').html(subtotal);
$('.totals.shipping').find('span.price').html(shipping);
$('.totals-tax').find('span.price').html(tax.toFixed(2));
$('.grand.totals').find('span.price').html(grandtotal);
$('.cart.item').each(function () {
var thiscartitem = $(this);
var subtotal = thiscartitem.find('.subtotal');
var subtotalval = subtotal.find('span.price');
var qty = thiscartitem.find('.qty');
var qtyval = qty.find('input.qty').val();
var price = thiscartitem.find('.price-wrapper');
var priceval = price.find('span.price').html();
var priceval = priceval.replace('€ ' , '');
var priceval = priceval.replace(',' , '.');
var subtotalafter = qtyval*priceval;
subtotalval.html('€ ' + (subtotalafter.toFixed(2)));
})
}
});
});
});
I hope i can help someone with this.