【发布时间】:2017-01-12 22:53:58
【问题描述】:
我正在从 JSON 数据创建一个可观察的数组。要么我最初创建的视图模型错误,要么我错误地将新数据添加到数组中。当我添加到数组后 console.log out 时,新添加的数据是不同的。
这是截图:
如您所见,brocCode=1800 之后的对象与数组中的所有先前项不同。我认为问题在于,当我在表格中添加新行时,我正在创建一个新的 itemModel 并将其添加到项目列表中。当我获取 JSON 数据并将其设为可观察数组时,我不会创建 itemModels 的可观察数组。
这是我的KnockoutJS:(具体看itemsModel中的self.addLine函数和self.items = ko.observableArray(items);):
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]);
}
GetItems() 在 Document.ready 上被调用。
【问题讨论】:
-
您需要使用
ko.mapping.fromJS()才能将现有itemsJSON中的所有属性转换为ko.observable()。试试var itemsJSON = ko.mapping.fromJS(@Html.Raw(...))(可能需要安装映射插件:knockoutjs.com/documentation/plugins-mapping.html) -
没有骰子,
Error: The argument passed when initializing an observable array must be an array, or null, or undefined. -
我想我需要以某种方式将其转换为 itemModel 数组
-
映射到模型数组:
ko.observableArray(items.map(function(data) { return new itemModel(data) })); -
@user3297291,这行得通!谢谢!如果您愿意,可以添加为答案。现在我只需要弄清楚为什么我的匹配(arrayFirst)函数不起作用。但我会为此发布另一个问题。
标签: knockout.js