敲除验证不适用于必需的项目
knockout validation not working on required items
我对 Knockout 很陌生,对使用 Knockout 验证更陌生。我有一些简单的必需输入,应该可以防止提交表单。它仍然提交空输入。我不确定我做错了什么。
我创建了一个fiddlehere。要进行测试,请在光标位于最后一个零售输入中时点击 Tab。这将添加一个新的空行。然后点击提交并查看控制台。
这是我的 javascript 代码:
var viewModel;
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null
}, true);
var itemModel = function () {
var self = this;
self.itemNo = ko.observable().extend( {required: true} );
self.brocCode = ko.observable().extend( {required: true} );
self.itemDesc = ko.observable().extend( {required: true} );
self.retail = ko.observable().extend( {required: true} );
}
var itemsModel = function(items) {
var self = this;
//self.items = ko.observableArray(items);
self.items = ko.mapping.fromJSON(items);
self.checkItemNo = function(data) {
console.log("blurred!");
var itemNo = "abc";
if (itemNo != "") {
var item = "";
/*
$.each(fullItemList, function(i, v) {
if (v.No.search(itemNo) != -1) {
item = v.Description;
return;
}
});
if(item != "") {
console.log("found: " + item);
var match = ko.utils.arrayFirst(self.items, function(item) {
return itemNo === item.itemNo;
});
*/
var match = false;
item = "Mudguard front";
if (!match) {
console.log("not a match!");
console.log(data);
data.itemDesc(item);
}
}
}
self.addLine = function() {
self.items.push( new itemModel() )
};
self.removeItem = function(item) {
self.items.remove(item);
};
self.errors = ko.validation.group(self.items);
};
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();
console.log("hit enter/tab!");
bindingContext.$root.addLine();
return false;
}
return true;
});
}
};
function GetItems() {
//var itemsJSON = @Html.Raw(Json.Encode(Model.brochureItems));
var itemsJSON = '[{"brochureId":1,"itemNo":"1000","brocCode":"1000","itemDesc":"Bicycle","retail":13.5},{"brochureId":1,"itemNo":"1100","brocCode":"1100","itemDesc":"Front Wheel","retail":35},{"brochureId":1,"itemNo":"1120","brocCode":"1120","itemDesc":"Spokes","retail":12.5},{"brochureId":1,"itemNo":"1150","brocCode":"1150","itemDesc":"Front Hub","retail":5},{"brochureId":1,"itemNo":"1151","brocCode":"1151","itemDesc":"Axle Front Wheel","retail":14},{"brochureId":1,"itemNo":"120","brocCode":"120","itemDesc":"Loudspeaker, Black, 120W","retail":12.5},{"brochureId":1,"itemNo":"125","brocCode":"125","itemDesc":"Socket Back","retail":10}]';
viewModel = new itemsModel(itemsJSON);
ko.applyBindings(viewModel);
}
$(document).ready(function () {
GetItems();
$('#brochureForm :submit').on('click', function(e) {
e.preventDefault(); //prevent form from submitting
if (viewModel.errors().length === 0)
//if(viewModel.validationModel.isValid())
{
console.log("submitting!");
//$("#brochureForm").submit();
}
else
{
console.log("not valid!");
}
});
});
我已经更新了你的 fiddle https://jsfiddle.net/q7ahfzut/2/。您的问题仅仅是由于分组时的配置所致。您需要添加 { deep: true }
,这将导致对所有已验证的可观察对象进行验证 运行 。您可以添加 live: true
,这将在向数组添加新项目时对 运行 进行验证。其他一些注意事项:
- 无需任何 jquery - 您可以对点击事件和提交使用 knockout
- 我从一开始就使用映射库为所有项目添加验证。
希望对您有所帮助!
更新
查看 ko 验证文档here 了解有关配置的更多信息
更新 2
要在您的评论中回答您的问题:请查看 mapping 用于敲除的插件以了解其工作原理(它的文档比验证要好一些。您可以 create
拦截映射以操作生成的 ViewModel。options.data
包含在映射到可观察对象之前映射的数据。了解它的最佳方法是阅读文档,然后通过单步执行来使用它慢慢来。
我对 Knockout 很陌生,对使用 Knockout 验证更陌生。我有一些简单的必需输入,应该可以防止提交表单。它仍然提交空输入。我不确定我做错了什么。
我创建了一个fiddlehere。要进行测试,请在光标位于最后一个零售输入中时点击 Tab。这将添加一个新的空行。然后点击提交并查看控制台。 这是我的 javascript 代码:
var viewModel;
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null
}, true);
var itemModel = function () {
var self = this;
self.itemNo = ko.observable().extend( {required: true} );
self.brocCode = ko.observable().extend( {required: true} );
self.itemDesc = ko.observable().extend( {required: true} );
self.retail = ko.observable().extend( {required: true} );
}
var itemsModel = function(items) {
var self = this;
//self.items = ko.observableArray(items);
self.items = ko.mapping.fromJSON(items);
self.checkItemNo = function(data) {
console.log("blurred!");
var itemNo = "abc";
if (itemNo != "") {
var item = "";
/*
$.each(fullItemList, function(i, v) {
if (v.No.search(itemNo) != -1) {
item = v.Description;
return;
}
});
if(item != "") {
console.log("found: " + item);
var match = ko.utils.arrayFirst(self.items, function(item) {
return itemNo === item.itemNo;
});
*/
var match = false;
item = "Mudguard front";
if (!match) {
console.log("not a match!");
console.log(data);
data.itemDesc(item);
}
}
}
self.addLine = function() {
self.items.push( new itemModel() )
};
self.removeItem = function(item) {
self.items.remove(item);
};
self.errors = ko.validation.group(self.items);
};
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();
console.log("hit enter/tab!");
bindingContext.$root.addLine();
return false;
}
return true;
});
}
};
function GetItems() {
//var itemsJSON = @Html.Raw(Json.Encode(Model.brochureItems));
var itemsJSON = '[{"brochureId":1,"itemNo":"1000","brocCode":"1000","itemDesc":"Bicycle","retail":13.5},{"brochureId":1,"itemNo":"1100","brocCode":"1100","itemDesc":"Front Wheel","retail":35},{"brochureId":1,"itemNo":"1120","brocCode":"1120","itemDesc":"Spokes","retail":12.5},{"brochureId":1,"itemNo":"1150","brocCode":"1150","itemDesc":"Front Hub","retail":5},{"brochureId":1,"itemNo":"1151","brocCode":"1151","itemDesc":"Axle Front Wheel","retail":14},{"brochureId":1,"itemNo":"120","brocCode":"120","itemDesc":"Loudspeaker, Black, 120W","retail":12.5},{"brochureId":1,"itemNo":"125","brocCode":"125","itemDesc":"Socket Back","retail":10}]';
viewModel = new itemsModel(itemsJSON);
ko.applyBindings(viewModel);
}
$(document).ready(function () {
GetItems();
$('#brochureForm :submit').on('click', function(e) {
e.preventDefault(); //prevent form from submitting
if (viewModel.errors().length === 0)
//if(viewModel.validationModel.isValid())
{
console.log("submitting!");
//$("#brochureForm").submit();
}
else
{
console.log("not valid!");
}
});
});
我已经更新了你的 fiddle https://jsfiddle.net/q7ahfzut/2/。您的问题仅仅是由于分组时的配置所致。您需要添加 { deep: true }
,这将导致对所有已验证的可观察对象进行验证 运行 。您可以添加 live: true
,这将在向数组添加新项目时对 运行 进行验证。其他一些注意事项:
- 无需任何 jquery - 您可以对点击事件和提交使用 knockout
- 我从一开始就使用映射库为所有项目添加验证。
希望对您有所帮助!
更新
查看 ko 验证文档here 了解有关配置的更多信息
更新 2
要在您的评论中回答您的问题:请查看 mapping 用于敲除的插件以了解其工作原理(它的文档比验证要好一些。您可以 create
拦截映射以操作生成的 ViewModel。options.data
包含在映射到可观察对象之前映射的数据。了解它的最佳方法是阅读文档,然后通过单步执行来使用它慢慢来。