qti*_*e67 1 knockout-mapping-plugin knockout.js knockout-validation
我正在尝试创建一个KnockoutJS视图模型,它模拟客户订单和许多订单商品.我想加载初始数据,并验证数据.
到目前为止,我可以使用knockoutjs.mapping加载数据,验证使用映射添加的数据.
// data to load into viewmodel
var modeldata = {
"OrderID":1,
"ReturnString":null,
"CustomerName":"First Customer",
"OrderDate":"2013-09-16T19:41:40.1639709+01:00",
"OrderItems": [
{"ItemID":0,
"ItemName":"Name_0",
"ItemPrice":0.0,
"_destroy":false
},
{"ItemID":1,
"ItemName":"Name_1",
"ItemPrice":10.0,
"_destroy":false
},
{"ItemID":2,
"ItemName":"Name_2",
"ItemPrice":20.0,
"_destroy":false
}
]
};
// setup defaults for validation
var validationOptions = {
insertMessages: true,
decorateElement: true,
errorElementClass: 'errorCSS',
messagesOnModified: true,
debug: true,
grouping: {
deep: true,
observable: false //Needed so added objects AFTER the initial setup get included
},
};
ko.validation.init(validationOptions);
// define array model
var Item = function () {
var self = this;
ItemID = ko.observable();
ItemName = ko.observable().extend({
required: { message: '* item name needed' }
});
ItemPrice = ko.observable();
_destroy = false;
}
// define view model
var ViewModel = function (data) {
var self = this;
self.OrderID = ko.observable();
self.ReturnString = ko.observable();
self.CustomerName = ko.observable().extend({
required: { message: '* customer name needed' }
});
self.OrderDate = ko.observable();
self.OrderItems = ko.observableArray([]); // to be array of "Item"
// create validation group
self.orderErrors = ko.validation.group(self);
self.orderItemErrors = ko.validation.group(
self.OrderItems, { deep: true }
);
self.lineItemsValid = function () {
var LValid = false;
if (self.orderItemErrors().length > 0) {
if (self.orderItemErrors()[0] != null) // important to test for null
LValid = false;
else
LValid = true;
}
else LValid = true
if (LValid) {
return true
}
else
{
self.orderItemErrors.showAllMessages();
return false;
}
}
self.orderValid = function () {
var LValid = false;
if (self.orderErrors().length > 0) {
if (self.orderErrors()[0] != null) // important to test for null
LValid = false;
else
LValid = true;
}
else LValid = true
if (LValid) {
return true
}
else {
self.orderErrors.showAllMessages();
return false;
}
}
self.isValid = function () {
if(self.orderValid() & self.lineItemsValid()){
alert('All ok!')
}
else{
alert('Errors!');}
}
// operations
self.addLineItem = function () {
self.OrderItems.unshift(new Item());
}
self.removeLineItem = function (item) {
self.OrderItems.destroy(item);
}
// load data into model
self.loadData = function () {
ko.mapping.fromJS(modeldata, {}, self);
}
}
$(document).ready(function () {
var viewModel = new ViewModel()
ko.applyBindings(viewModel);
});
Run Code Online (Sandbox Code Playgroud)
问题:
(1)我也可以使用click函数添加订单项,但是这些数据似乎没有在可观察数组中更新.但是,当我调用"删除"项目函数时,数组项被标记为已删除.
(2)当我使用映射加载项目并测试验证(required = true)时,它仅适用于通过映射加载的项目,而不适用于我在映射完成后添加的订单项目
(3)当我更新通过映射引入的订单项时,更改立即反映在可观察数组中,当我更新映射后添加的订单项时,数组中没有更新.
我有一个JSFiddle:
http://jsfiddle.net/devops/ZsDjh/40/
我确信它与我如何添加到可观察数组有关但却看不到任何明显的东西 - 我显然缺少一些基本的东西......如果有人有任何想法?
谢谢
总共只有一些小的疏忽.
首先,让我们跳到(3)
(3)当我更新通过映射引入的订单项时,更改立即反映在可观察数组中,当我更新映射后添加的订单项时,数组中没有更新.
在Item函数中,属性必须绑定到此(self).
var Item = function () {
var self = this;
self._destroy = false;
self.ItemID = ko.observable();
self.ItemName = ko.observable().extend({ required: { message: '* item name needed' } });
self.ItemPrice = ko.observable();
}
Run Code Online (Sandbox Code Playgroud)
现在为(2),
(2)当我使用映射加载项目并测试验证(required = true)时,它仅适用于通过映射加载的项目,而不适用于我在映射完成后添加的订单项目
这是因为您使用映射插件的方式以及如何向OrderItems observableArray添加新项目.
// load data into model
self.loadData = function () {
ko.mapping.fromJS(modeldata, {}, self);
}
Run Code Online (Sandbox Code Playgroud)
我无法从你的小提琴中复制这个,但我非常清楚可能发生的事情.
由于映射插件只是从您的JSON创建可观察属性并分别在self上分配(或在您的情况下重新分配)属性,因此不知道数组中的每个OrderItems对象都是新的Item()对象.它只是创建匿名的可观察对象并将它们放在一个新的observableArray中,然后将其分配给self.OrderItems.
您必须指示映射器如何处理您的数组.
// outside your viewmodel
var itemMapping = {
create: function (options) {
return new Item(options.data);
}
};
// load data into model
self.loadData = function () {
ko.mapping.fromJS(modeldata, { OrderItems: itemMapping }, self);
}
Run Code Online (Sandbox Code Playgroud)
现在我们将JSON数组中的每个项目传递给itemMapping的create函数.但是,我们现在有一个问题.Item函数不带任何参数.所以我们来修复它.而且,虽然在它,让我们让mapper再次帮助我们创建我们的项目的可观察属性.
var Item = function (data) {
var self = this;
self._destroy = false;
//self.ItemID = ko.observable(data.ItemID);
//self.ItemName = ko.observable(data.ItemName).extend({ required: true });
//self.ItemPrice = ko.observable(data.ItemPrice);
ko.mapping.fromJS(data, {}, self);
self.ItemName.extend({ required: { message: '* item name needed' } });
}
Run Code Online (Sandbox Code Playgroud)
由于我们已经修改了Item函数,我们需要更新addLineItem方法.
// operations
self.addLineItem = function () {
// set the default values
self.OrderItems.unshift(new Item({ ItemId: null, ItemName: "", ItemPrice: 0 }));
}
Run Code Online (Sandbox Code Playgroud)
现在,摆脱你的self.lineItemsValid和self.orderValid方法并删除你的self.orderItemErrors属性.
重命名并更新您的isValid方法.
self.checkValid = function () {
if(self.isValid()){
alert('All ok!');
}
else{
self.orderErrors.showAllMessages();
}
}
Run Code Online (Sandbox Code Playgroud)
self.isValid()是验证插件创建的方法.你覆盖了它.
并且,更新您的HTML.
<a href="#" data-bind="click: checkValid">Check is valid</a>
Run Code Online (Sandbox Code Playgroud)
最后(1),
(1)我也可以使用click函数添加订单项,但是这些数据似乎没有在可观察数组中更新.
这是通过我们对Item函数所做的修改来修复的.
但是,当我调用"删除"项目函数时,数组项被标记为已删除.
我不确定您是否希望将其完全删除或仅标记为_destroyed.
如果您只是想删除它,请更新您的removeLineItem方法.
self.removeLineItem = function (item) {
self.OrderItems.remove(item);
}
Run Code Online (Sandbox Code Playgroud)
请参阅Observable Arrays的淘汰文档,阅读有关删除和销毁方法的信息,以确定最适合您的方法.
这是修改后的jsFiddle.
干杯!
PS请+1,因为这个答案给你的车轮上油了!:)
归档时间: |
|
查看次数: |
3599 次 |
最近记录: |