如何在数量发生变化时自动更新合计

How to automatically update the grandtotal when quantity is changed

本文关键字:更新 变化      更新时间:2023-09-26

我的购物车使用淘汰,我似乎无法根据商品的变化自动更新总金额。

查看

<div data-bind="foreach: cartItems">
 <div class="row item-row">
  <h3 data-bind="text: fullname"></h3>
  <p data-bind="text: sku"></p>
  <select data-bind="quantityDropdown: number, event: {change: $parent.updateqty}"></select>
 </div>
</div>
<div class="row">
    <p class="checkout-box-totals">Subtotal:</p>
    <p class="checkout-box-price">
        <span class="glyphicon glyphicon-usd" data-bind="text: subtotal()"></span>
    </p>
</div>
<hr/>
<div class="row checkout-box-total">
    <p class="checkout-box-totals">Total:</p>
    <p class="checkout-box-price">
        <span class="glyphicon glyphicon-usd" data-bind="text: grandTotal()"></span>
    </p>
</div>

VIEWMODEL

    //This items placed in cart is placed in my cookiearray
    //cookiearray contains = datetime, id, typeid, qty, fullname, image, price, sku, weight)
    var cookiestring = $.cookie("cookieCart");
    var arrayfromJson = JSON.parse(cookiestring);
    //Deletes the cookie
    var deleteCookie = function (name) {
      document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:01 GMT;";
    };
    function UpdateCookieQty(id, typeid, select) {
       for (var i = arrayfromJson.length - 1; i >= 0; i--) {
           if (arrayfromJson[i].id === id && arrayfromJson[i].typeid === typeid) {
               arrayfromJson[i].qty = select;
           }
       }
       //recreates the cookie string after updating the quantity. This new quantity isnt read in the observable until browser is refreshed.
       deleteCookie("cookieCart");
       $.cookie("cookieCart", JSON.stringify(arrayfromJson), { path: "/" });
   }

function AppViewModel() {
    var self = this;
    self.cartItems = ko.observableArray(arrayfromJson);
    self.quantity = ko.observable(); //here im trying to make the quantity observable.
    var totalShipWeight = 0;
    //calculating total weight of the cart
    for (var n = 0; n < self.cartItems().length; n++) {
        var itemweight = parseFloat(arrayfromJson[n].weight, 10);
        var shipqty = parseFloat(arrayfromJson[n].qty, 10);
        totalShipWeight += itemweight * shipqty;
    }
    //calculating the subtotal doesn't update when quantity is changed :(
    self.subtotal = ko.computed(function () {
        var total = 0;
        for (var i = 0; i < self.cartItems().length; i++) {
            var itemPrice = parseFloat(arrayfromJson[i].price, 10);
            var itemqty = parseFloat(arrayfromJson[i].qty, 10);
            total += itemPrice * itemqty;
        }
        return total;
    });
    //calculating tax if tax applies, doesn't update when quantity is changed
    self.taxedItems = ko.pureComputed(function () {
        var taxcost = 0;
        var total = 0;
        if (totalShipWeight > 0) {
            for (var i = 0; i < self.cartItems().length; i++) {
                var itemPrice = parseFloat(arrayfromJson[i].price, 10);
                var itemqty = parseFloat(arrayfromJson[i].qty, 10);
                total += itemPrice * itemqty;
            }
            taxcost = parseFloat((total * tax).toFixed(2));
        } 
        return taxcost;
    });
    //calculating tax if tax applies, doesn't update when quantity is changed
    self.grandTotal = ko.pureComputed(function () {
        var total = 0;
        var grandTotal = 0;
        for (var i = 0; i < self.cartItems().length; i++) {
            var itemPrice = parseFloat(arrayfromJson[i].price, 10);
            var itemqty = parseInt(arrayfromJson[i].qty, 10);
            total += itemPrice * itemqty;
        }
        grandTotal = total + (total * tax);
        //Add shipping cost
        return grandTotal;
    });
    //number = 50 from controller. this is just to display dropdown for max amount of quantity
    ko.bindingHandlers.quantityDropdown = {
        update: function (element) {
            for (var i = 1; i < number + 1; i++) {
                var selectedQty = "";
                for (var x = 0; x < self.cartItems().length; x++) {
                    var itemqty = parseFloat(arrayfromJson[x].qty, 10);
                    if (i === itemqty) {
                        selectedQty = " selected='selected'";
                    }
                }
                // Add each option element to the select here
                $(element).append("<option value='" + i + "' " + selectedQty + ">" + i + "</option>");
            }
        }
    };

    //this is where the user updates quantity. I goes to the function, 
    //updates quantity for particular item (but for some reason updates both items).
    //then the change is supposed to reflect in the subtotal and grandtotal, but doesnt.
    self.updateqty = function (viewModel, event) {
        UpdateCookieQty(this.id, this.typeid, event.target.value);
        }
    }
    ko.applyBindings(new AppViewModel());

我对淘汰赛还很陌生,但这里有什么问题吗?

所以问题是你只更新arrayFromJson,而淘汰赛对此一无所知,所以它不知道需要来更新你计算的grandTotal。并不是所有的代码都显示出来了,所以我不确定所有函数和实例的范围,但本质上,你只需要告诉knockout重新计算grandTotal,理想情况下,你可以从UpdateCookie函数中这样做:

function UpdateCookieQty(id, typeid, select) {
   for (var i = arrayfromJson.length - 1; i >= 0; i--) {
       if (arrayfromJson[i].id === id && arrayfromJson[i].typeid === typeid) {
           arrayfromJson[i].qty = select;
       }
   }
   //recreates the cookie string after updating the quantity. This new quantity isnt read in the observable until browser is refreshed.
   deleteCookie("cookieCart");
   $.cookie("cookieCart", JSON.stringify(arrayfromJson), { path: "/" });
   myAppViewModel.cartItems.removeAll();
   ko.utils.arrayPushAll(myAppViewModel.cartItems, arrayFromJson);
}

注意这里的.removeAll()arrayPushAll()调用,人们在敲除时会犯一个常见的错误,这样可以避免。你想确保你没有在这里做:myAppViewModel.cartItems = ko.observableArray(arrayFromJson);(再次)。这将用新的可观察对象替换原始可观察对象,并放弃computed对原始实例的所有订阅。

完成后,更新您的计算值以依赖于cartItems,因为它可观察的,因此淘汰将检测到它的变化,然后自动为您重新计算值。

self.grandTotal = ko.pureComputed(function () {
    var total = 0;
    var grandTotal = 0;
    for (var i = 0; i < self.cartItems().length; i++) {
        var itemPrice = parseFloat(cartItems[i].price, 10);
        var itemqty = parseInt(cartItems[i].qty, 10);
        total += itemPrice * itemqty;
    }
    grandTotal = total + (total * tax);
    //Add shipping cost
    //Discount CMEZ
    return grandTotal;
});