我一直在MVC 5 Web App中使用knockoutjs(3.3.0)和knockout-validation(2.0.3)来创建一个表单,该表单除了其他字段外,还根据另一个字段动态显示多个选择列表对选择列表值(即选择一个停止次数,并显示正确的目的地/持续时间对数)。
Knockout验证适用于所有其他字段,使用下面的代码,除了动态添加的目标/持续时间对,我可以看到失败验证,(如果你不选择目的地),但它失败了选中时更新并通过验证。我尝试在init和viewmodel中设置{deep:true}分组,但仍然没有飞镖。
这是https://jsfiddle.net/2c9o2cpu/39/
下面代码的缩写Destination = function (name, value) {
var self = this;
this.name = ko.observable(name).extend({
required: true
});
this.value = ko.observable(value).extend({
required: true
}).extend({
min: 1
});
self.errors = ko.validation.group(self);
}
Duration = function (name, value) {
var self = this;
this.name = ko.observable(name).extend({
required: true
});
this.value = ko.observable(value).extend({
required: true
});
self.errors = ko.validation.group(self);
}
function EnquiryViewModel() {
var self = this;
self.Stops = ko.observable([{
"Id": 1,
"Name": "1 stop"
}, {
"Id": 2,
"Name": "2 stops"
}, {
"Id": 3,
"Name": "3 stops"
}, {
"Id": 4,
"Name": "4 stops"
}]);
self.selectedTitle = ko.observable();
self.selectedStops = ko.observable();
self.Destinations = ko.observable([{
"Id": 0,
"Name": "Destination?"
}, {
"Id": 2,
"Name": "San Francisco"
}, {
"Id": 3,
"Name": "Wine Country"
}, {
"Id": 4,
"Name": "Mountain Areas"
}]);
self.selectedDestination = ko.observable();
self.Durations = ko.observable([{
"Id": 1,
"Name": "1 night"
}, {
"Id": 2,
"Name": "2 nights"
}, {
"Id": 3,
"Name": "3 nights"
}]);
self.selectedDuration = ko.observable();
self.FirstName = ko.observable().extend({
required: true
});
self.destinationData = ko.observableArray([]);
self.destinationlistData = ko.observable({});
self.datadest = ko.observable({});
self.durationData = ko.observableArray([]);
self.durationlistData = ko.observable({});
self.datadur = ko.observable({});
self.fieldNum = 0;
// predefine observables for those shown
self.destinationlistData()["field0"] = ko.observableArray([]);
self.durationlistData()["field0"] = ko.observableArray([]);
self.datadest()["field0"] = ko.observable();
self.datadur()["field0"] = ko.observable();
self.removeDestination = function (item) {
self.destinationData.remove(item);
self.durationData.remove(item);
self.fieldNum--;
}
self.addDestination = function () {
var field = "field" + self.fieldNum++;
if (!ko.isObservable(self.destinationlistData()[field])) self.destinationlistData()[field] = ko.observableArray([]);
if (!ko.isObservable(self.datadest()[field])) self.datadest()[field] = ko.observable();
if (!ko.isObservable(self.durationlistData()[field])) self.durationlistData()[field] = ko.observableArray([]);
if (!ko.isObservable(self.datadur()[field])) self.datadur()[field] = ko.observable();
// populate destinations
var data1 = '[{"Id":0,"Name":"Destination?"},{"Id":2,"Name":"San Francisco"},{"Id":3,"Name":"Wine Country"},{"Id":4,"Name":"Mountain Areas"}]';
//self.destinationlistData()[field].push(new Destination("Destination?", 0));
$.each($.parseJSON(data1), function (i, dest) {
self.destinationlistData()[field].push(new Destination(dest.Name, dest.Id));
});
var data2 = '[{"Id":1,"Name":"1 night"},{"Id":2,"Name":"2 nights"},{"Id":3,"Name":"3 nights"}]';
self.durationlistData()[field].push(new Duration("Duration?", 0));
$.each($.parseJSON(data2), function (i, dur) {
self.durationlistData()[field].push(new Duration(dur.Name, dur.Id));
});
self.destinationData.push(field);
self.durationData.push(field);
}
self.addDestination();
self.Save = function () {
if (self.errors().length === 0) {
var jsonData = ko.toJSON(self);
//console.log(jsonData);
// for now, post the entire thing as a string. We'll trim this down with a model
//$.post("/Home/Save", { jsonData: jsonData });
alert("Validation Passed");
} else {
alert('Validation Failed');
console.log(self.errors().length);
console.dir(self.errors);
self.errors.showAllMessages();
}
};
//self.errors = ko.validation.group(self, { deep: true });
self.errors = ko.validation.group(self);
self.stopsChanged = function (obj, event) {
if (event.originalEvent) { // user
var stops = self.selectedStops();
if (stops === 0) {
self.destinationData.removeAll();
self.durationData.removeAll();
}
if (stops < self.destinationData().length) {
self.destinationData.splice(stops);
self.durationData.splice(stops);
} else {
if (stops >= 1) {
var existing = self.destinationData().length || 0;
for (var i = 0; i < (stops - existing); i++) {
self.addDestination();
}
}
}
} else { // system
// ..
}
}
}
ko.validation.init({
registerExtenders: true,
decorateElement: true,
errorElementClass: 'err',
errorMessageClass: 'err',
insertMessages: true,
decorateInputElement: true,
//grouping: { deep: true },
messagesOnModified: false
}, true);
var vm = new EnquiryViewModel();
ko.applyBindings(vm, document.getElementById("test"));