简体   繁体   English

淘汰赛JS购物车练习

[英]Knockout JS shopping cart exercise

I am learning knockout js and have begun building a simple shopping cart. 我正在学习淘汰赛js,并已开始构建简单的购物车。

This shopping cart basically ask the user to select a category from a dropdownlist and then a second dropdownlist is then populated with products. 该购物车基本上要求用户从下拉列表中选择类别,然后在第二个下拉列表中填充产品。

When the user selected a product, the product information is displayed ie name/price/qty/total. 当用户选择产品时,将显示产品信息,即名称/价格/数量/总计。 An 'add Item' button is also visible. “添加项目”按钮也是可见的。

the qty data is a textbook where the user can increment the value. 数量数据是一本教科书,用户可以在其中增加该值。 If the user increments the qty value the total value will calculate the new total ie (price * qty). 如果用户增加数量值,则总价值将计算新的总和,即(价格*数量)。

When the user clicks the add item button the product id, name, qty and total are stored and displayed (except id) in an adjacent div ie cart list. 当用户单击添加项目按钮时,产品ID,名称,数量和总数将存储并显示在相邻的div(即购物车列表)中(ID除外)。

The problem i am having is that when an item is in the shopping cart with qty 1 and i want to add a new item to the cart with a qty of 2. The qty value in the cart is also changing to 2. The values should stay at 1 also the total value in the shopping cart is matching that of the new item. 我遇到的问题是,当某商品位于数量为1的购物车中,并且我想向数量为2的购物车中添加新商品时,购物车中的数量值也更改为2。这些值应保持为1时,购物车中的总价值也将与新商品的总价值匹配。

here is the code: 这是代码:

<div id="exp2">
    <div>
        <span>
            <select id="ddlCat" data-bind="options: lstCategories, optionsText: 'name',
            optionsValue: 'id', optionsCaption: 'Select Category...',
            value: selectedCate"></select>
        </span>
        <span data-bind="visible: lstProducts().length > 0">
            <select id="ddlProd" data-bind="options: lstProducts, optionsText: 'name',
            optionsValue: 'id',  optionsCaption: 'Select Product...',
            value: selectedProdId"></select>
        </span>
        <span data-bind="with: selectedProd()">
            Price: £<span id="pPrice" data-bind="text: price"></span>, &nbsp;
            Qty <input type="text" id="pQty" data-bind="value: quantity" style="width:30px;"
                       placeholder="" required />
            SubTotal: £<span data-bind="text: itemTotal()"></span>
            <span><button id="btnAdd" class="btnAdd" data-bind="click: addItem">Add to cart</button></span>
        </span>
    </div>
    <div>
        <h3>Items In Cart</h3>
        <ul id="lstCart" data-bind="foreach: cart">
            <li>
                Name: <span data-bind="text: name"></span>&nbsp;
                Qty: <span data-bind="text: qty"></span>&nbsp;
                Item Total: £<span data-bind="text: itemTotal"></span>&nbsp;
            </li>
        </ul>
        Sub Total: £<span data-bind="text: subTotal()"></span>
    </div>
  </div>

Javascript Java脚本

        var categories = [];
        var products = [];
        var cartLines = [];

        $.ajax({
            url: '../KnockoutTut/page5GetCat',
            type: "GET", cache: false, async: false,
            contentType: "application/json; charset=utf-8",
            dataType: "json", traditional: true,
            success: function (data) {
                //alert('Process Successful');
                for (var i = 0; i < data.length; i++) {
                    var id = data[i].id; var name = data[i].name;
                    //var nCat = new Category(id, name);
                    categories.push( new Category(id,name));
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                //alert("Error")
                alert(jqXHR.status + "," + jqXHR.responseText + "," + errorThrown);
            }
        });

        function getProd(catId) {
            products = [];
            var value = { 'value': catId };
            var json = JSON.stringify(value);
            $.ajax({
                url: '../KnockoutTut/page5GetProd',
                type: "POST", data: json, cache: false, async: false,
                contentType: "application/json; charset=utf-8",
                dataType: "json", traditional: true,
                success: function (data) {
                    //alert('Process Successful');
                    for (var i = 0; i < data.length; i++) {
                        var id = data[i].id; var name = data[i].name;
                        var price = data[i].price; var qty = data[i].qty;
                        products.push(new Product(id, name, price, 1));
                    }
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    //alert("Error")
                    alert(jqXHR.status + "," + jqXHR.responseText + "," + errorThrown);
                }
            });
        }

        function Category(id, name) {
            this.id = id;
            this.name = name;
        };

        function Item(id, name, qty, itemTotal) {
            this.id = id;
            this.name = name;
            this.qty = qty;
            this.itemTotal = itemTotal;
        };

        function Product(id, name, price, qty) {
            this.id = id;
            this.name = name;
            this.price = price;
            this.qty = qty;
        };

        function viewModel() {

            var self = this;
            self.lstCategories = ko.observableArray(categories);
            self.lstProducts = ko.observableArray([]);
            self.cart = ko.observableArray([]);
            self.selectedCate = ko.observable();
            self.selectedProdId = ko.observable();
            self.selectedProd = ko.observable();
            self.quantity = ko.observable(1);
            self.catQty = ko.observable();

            self.itemTotal = ko.pureComputed(function () {
                return self.selectedProd() ? self.selectedProd().price * parseInt("0" + self.quantity(), 10) : 0;
            });

            self.subTotal = ko.pureComputed(function () {
                var total = 0;
                $.each(self.cart(), function () { total += this.itemTotal() })
                return total;
            });

            self.selectedCate.subscribe(function (pCatId) {
                var catId = pCatId;
                if ($.isNumeric(catId)) {
                    getProd(catId);
                }
                self.lstProducts(products);
            });

            self.selectedProdId.subscribe(function (pProdId) {
                var pId = pProdId;
                var match = ko.utils.arrayFirst(lstProducts(), function (item) {
                    return pId === item.id;
                });
                self.selectedProd(match);
                //alert(selectedProd().qty);
            });

            self.addItem = function (item) {
                var nId = item.id; var nName = item.name; var cartQty = quantity; var iTot = itemTotal;
                cart.push(new Item(nId, nName, cartQty, iTot));
                //cart.push(cartLines);
            };                
        };
        ko.applyBindings(viewModel, document.getElementById("exp2"));

Remember i am new to knockout js. 记住我是淘汰JS的新手。 so please excuse the bad coding. 因此,请原谅错误的编码。 Thanks 谢谢

The issues seems to be with what value are you using for showing the data after an item has been added. 问题似乎在于添加项目后使用什么值显示数据。 If I am not wrong, you are assigning observable to the property cartQty inside of the cart array. 如果我没看错,您正在将可观察值分配给cart数组内的属性cartQty Since, you are using the added values in cart just to show as label information and user is not supposed to change that (unless of course after deleting that record and then adding a new one after the desired modifications), there is no need to use two way binding and hence no need to assign observable like you are doing here - 因为,您只是在cart中使用添加的值来显示标签信息,并且用户不应该对此进行更改(除非删除该记录,然后在所需的修改后添加一个新记录),否则无需使用双向绑定,因此无需像您在此处所做的那样分配可观察的对象-

var cartQty = quantity;

So, it is always better to separate these by assigning only the value enclosed by the observable, rather than the observable itself. 因此,最好只分配可观察对象包围的值而不是可观察对象本身来将它们分开。

You can try something like this - 您可以尝试这样的事情-

var cartQty = quantity();

So that changing the quantity does not have its side effects elsewhere. 因此,更改数量不会在其他地方产生副作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM