我正在从JSON数据创建一个可观察的数组。要么我最初创建viewmodel错误,要么我错误地向数组添加新数据。当我在添加数据库后调试数组时,新添加的数据是不同的。
以下是截图:
正如您所看到的,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()
。
答案 0 :(得分:1)
您的itemsJSON
是一组普通对象。尽管他们可能看起来像<{1}}(他们共享相同的属性名称),但它们之间存在很大差异:他们不具有可观察的属性值,您的价值也不会通过您的扩展程序验证。
在itemModel
方法中,您可以通过调用addLine
正确地实例化新的itemModel
。因此,您的可观察数组将包含普通对象和new itemModel()
实例的混合。这不是一个问题,但如果您希望能够轻松处理数组的值,那么确保它们共享相同的类型会更好。
您可以通过迭代itemModel
中的对象将初始数据映射到正确的视图模型:
itemsJSON
我建议您遵循命名约定并将var itemModels = itemsJSON.map(function(data) {
return new itemModel(data);
});
重命名为itemModel
。如果它适合您的样式,您可以创建一个静态辅助方法,为您返回一个新实例:
ItemModel