项目未正确添加到可观察数组

时间:2017-01-12 14:18:48

标签: knockout.js

我正在从JSON数据创建一个可观察的数组。要么我最初创建viewmodel错误,要么我错误地向数组添加新数据。当我在添加数据库后调试数组时,新添加的数据是不同的。 以下是截图:enter image description here 正如您所看到的,brocCode=1800之后的对象与数组中的所有先前项不同。我认为问题在于,当我向表中添加新行时,我正在创建一个新的itemModel并将其添加到项列表中。当我获取JSON数据并使其成为可观察数组时,我没有创建itemModel s的可观察数组。

这是我的KnockoutJS :(具体看看self.items = ko.observableArray(items);中的self.addLine函数和itemsModel):

var itemModel = function (data) {
        var self = this;
        self.invalidItem = ko.observable(true);
        self.itemNo = ko.observable(data ? data.itemNo : '').extend( {
            required: {
                params: true,
                message: "Item no. required."
            }
        });
        self.brocCode = ko.observable(data ? data.brocCode : '').extend( {
            required: {
                params: true,
                message: "Bro code required."
            }
        });
        self.itemDesc = ko.observable(data ? data.itemDesc : '').extend( {
            required: {
                params: true,
                message: "Item desc required."
            }
        });
        self.retail = ko.observable(data ? data.retail : '').extend( {
            required: {
                params: true,
                message: "Retail required."
            }
        })
        .extend({numeric: 2});
        self.prizeNum = ko.observable(data ? data.prizeNum : '').extend( {
            required: {
                params: true,
                message: "Prize num required."
            }
        });
        self.itemOrder = ko.observable(data ? data.itemOrder : '').extend( {
            required: {
                params: true,
                message: "Item order required."
            }
        });
    }

    var itemsModel = function(items) {
        var self = this;
        self.items = ko.observableArray(items);
        //self.items = ko.mapping.fromJSON(items, itemModel);

        self.invalidItem = ko.observable(true);

        self.checkItemNo = function(data) {
            //console.log("lost focus - " + self.invalidItem());
            var itemNo = $.trim(data.itemNo());
            console.log(itemNo);
            if (itemNo != "") {
                var item = "";
                $.each(window.listOfItems, function(i, v) {
                    if (v.No.search(itemNo) != -1) {
                        item = v.Description;
                        return;
                    }
                });
                console.log(item);
                if(item != "") {
                    console.log(self.items());
                    var match = ko.utils.arrayFirst(self.items(), function(newItem) {
                        console.log("checking " + newItem.itemNo);
                        return itemNo === newItem.itemNo;
                    });
                    console.log("match: " + match);
                    if (!match) {
                        data.itemDesc(item);
                    } else { // item already entered
                        data.invalidItem(true);
                        setTimeout(function() { data.invalidItem(true); }, 1);
                        data.itemDesc("");
                        slideDownMsg("Item already entered.");
                        slideUpMsg(3000);
                    }
                } else { // invalid item #
                    console.log(data);
                    data.invalidItem(true);
                    setTimeout(function() { data.invalidItem(true); }, 1);
                    data.itemDesc("");
                    slideDownMsg("Invalid item number.");
                    slideUpMsg(3000);
                }
            }
        }

        self.submit = function() {
            //self.showErrors(true);
            if (viewModel.errors().length === 0) {
                console.log('Thank you.');
                $("#brochureForm").submit();
            }
            else {
                console.log('Please check your submission.');
                viewModel.errors.showAllMessages();
                $(".input-validation-error").first().focus();
            }
        }

        self.addLine = function() {
            var iModel = new itemModel();
            iModel.invalidItem(true);
            self.invalidItem(true);
            console.log("adding new line; it is: " + self.invalidItem());
            self.items.push( iModel );
            //setTimeout(function() { self.invalidItem(true); }, 1);
        };

        self.insertLine = function(index) {
            self.items.splice(index, 0, new itemModel() );
        };

        self.removeItem = function(item) {
            self.items.remove(item);
        };

        self.errors = ko.validation.group(self.items, { deep: true, live: true });

        self.validate = function() {
            self.errors.showAllMessages();
        }
    };

    var profitCode = function(code, desc, name) {
        this.code = code;
        this.desc = desc;
        this.name = name;
    };

    var codeModel = function(codes) {
        var self = this;
        self.availableProfitCodes = ko.observableArray([])
        self.codes = ko.observableArray(codes);
    }

    var profitItemsModel = function(items) {
        var self = this;
        self.items = ko.observableArray(items);
    }

    var combined = (function () {
        function combinedVM() {
            this.codes = ko.observable(codeModel);
            this.items = ko.observable(profitItemsModel);
            this.availableProfitCodes = codeModel.availableProfitCodes;
        }
        return combinedVM;
    })();

    ko.bindingHandlers.enterPress = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var allBindings = allBindingsAccessor();
            element.addEventListener('keydown', function (event) {
                var keyCode = (event.which ? event.which : event.keyCode);
                if (keyCode === 13 || (!event.shiftKey && keyCode === 9)) {
                    event.preventDefault();
                    //bindingContext.$root.invalidItem(false);
                    bindingContext.$root.addLine();
                    return false;
                }
                return true;
            });
        }
    };

    ko.bindingHandlers.insertPress = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var allBindings = allBindingsAccessor();
            element.addEventListener('keydown', function (event) {
                var keyCode = (event.which ? event.which : event.keyCode);
                if (keyCode === 45) {
                    event.preventDefault();
                    bindingContext.$root.insertLine(ko.unwrap(valueAccessor()));
                    return false;
                }
                return true;
            });
        }
    };

    ko.bindingHandlers.selected = {
        update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var selected = ko.utils.unwrapObservable(valueAccessor());
            if (selected) element.select();
        }
    };        

    function GetItems() {
        var itemsJSON = @Html.Raw(Json.Encode(Model.brochureItems));
        viewModel = new itemsModel(itemsJSON);
        ko.applyBindings(viewModel, $("#itemListContainer")[0]);
    }
在Document.ready上调用

GetItems()

1 个答案:

答案 0 :(得分:1)

您的itemsJSON是一组普通对象。尽管他们可能看起来像<{1}}(他们共享相同的属性名称),但它们之间存在很大差异:他们具有可观察的属性值,您的价值也不会通过您的扩展程序验证。

itemModel方法中,您可以通过调用addLine正确地实例化新的itemModel。因此,您的可观察数组将包含普通对象和new itemModel()实例的混合。这不是一个问题,但如果您希望能够轻松处理数组的值,那么确保它们共享相同的类型会更好。

您可以通过迭代itemModel中的对象将初始数据映射到正确的视图模型:

itemsJSON

我建议您遵循命名约定并将var itemModels = itemsJSON.map(function(data) { return new itemModel(data); }); 重命名为itemModel。如果它适合您的样式,您可以创建一个静态辅助方法,为您返回一个新实例:

ItemModel