如何将 ko.validation 错误与相关的视图模型字段名称联系在一起
Posted
技术标签:
【中文标题】如何将 ko.validation 错误与相关的视图模型字段名称联系在一起【英文标题】:How to tie together ko.validation errors with related viewmodel field names 【发布时间】:2013-08-10 08:45:07 【问题描述】:我正在使用 Knockout.Validation 并且我希望能够显示错误摘要,其中每一行都显示错误消息(显然!)以及与之相关的视图模型上的字段名称,例如
年龄 - 请输入数字 出生日期 - 请输入正确的日期到目前为止,我已经有一个经过验证的Observable 包装了我的视图模型,这会自动在我的视图模型上放置一个错误数组,其中包含我的所有错误。但是我看不到任何简单的方法来检索每个错误与哪个字段相关。
我知道我可以自己遍历视图模型,从 isValid 属性建立我自己的错误集合 - 这是我唯一的选择吗?
获得字段名称后,我可以将验证摘要映射到该字段的相关“友好”标签(例如“出生日期”而不是“出生日期”)。
这是我目前所拥有的代码的简化版本:
视图模型
function PersonModel()
var self = this;
self.Age = ko.observable().extend( number: true);
self.DateOfBirth = ko.observable( date: true);
self.Validate = function()
if (!self.isValid())
self.errors.showAllMessages();
return false;
return true;
;
ko.validation.init(
grouping: deep: true, observable: true ,
registerExtenders: true,
messagesOnModified: true,
insertMessages: true
);
ko.applyBindings(ko.validatedObservable(new PersonModel()));
<ul data-bind='foreach: model().errors' class="message">
<li>
<span data-bind='text: $data'></span>
</li>
</ul>
非常感谢
【问题讨论】:
可以分享一下你目前掌握的相关代码吗? 【参考方案1】:您可以对任何变量使用自定义验证消息。
emailAddress: ko.observable().extend(
required: message: 'Email Address: Required field.'
),
【讨论】:
当你有两个相同的东西被验证时,这就会崩溃 - 例如,账单和送货地址都有相同的字段 它们不应该是相同的可观察对象,淘汰赛验证要求您扩展每个个体(可观察对象),这将被验证。您可以对邮政地址使用 onlyif 验证规则或其他一些自定义规则 github.com/Knockout-Contrib/Knockout-Validation/wiki/…。【参考方案2】:您可以执行以下操作:
添加一个friendlyName
扩展器,为您的 observables 提供一个友好的名称
破解显示消息的绑定处理程序
好听的名字:
有史以来最简单的淘汰赛延长器:
ko.extenders.friendlyName = function (obs, options)
obs.friendlyName = options;
用法:self.Age = ko.observable(3).extend( friendlyName: "My Age" );
显示消息破解:
敲除验证插件创建一个绑定处理程序validationMessage
来显示错误消息。您可以直接使用它(带有一些 html 标记)或让插件使用配置选项 insertMessages
处理消息。
这里我只是编辑它创建的 html(仍然调用原始绑定处理程序)以考虑 friendlyName
:
var originalValidationMessageUpdate= ko.bindingHandlers.validationMessage.update;
ko.bindingHandlers.validationMessage.update =
function (element, valueAccessor, allBindingAccessor, viewModel,
bindingContext)
if (originalValidationMessageUpdate)
originalValidationMessageUpdate(element, valueAccessor,
allBindingAccessor, viewModel,
bindingContext);
var prepend = (ko.isObservable(valueAccessor())
&& valueAccessor().friendlyName)
? valueAccessor().friendlyName + " - "
: "";
$(element).html(prepend + $(element).html());
// ^^^^ This is the line that is actually useful
注意:我没有将friendlyName
创建为可观察对象,因为我猜它不会被更新,但可以这样做。
Demo
【讨论】:
我会接受这个想法,谢谢。很遗憾,他们不能在 Ko.Validation 中加入一些东西来提供帮助 - 可能会建议! @philicomus 好吧,你可以contribute :)【参考方案3】:我发现这很好用 - 在控制台中输入 (F12):
for(var propertyName in PersonModel())
console.log(ko.validation.group(PersonModel()[propertyName])())
这会给你类似的东西:
[]
[]
[]
[This field is required.]
[]
[]
然后,您可以将问题字段绑定到模型中的属性。 在本例中,问题出在第 4 个属性上。
我希望这对某人有所帮助。
【讨论】:
丑陋,但有效,什么是淘汰赛验证没有经过验证的 observable 的名称?【参考方案4】:很遗憾,您需要为每个验证器指定消息,除非您按照 GôTô 的建议执行完全自定义的操作。
想一想……您还没有为您的字段指定显示名称,那么 ko 验证应该如何知道验证错误消息的字段名称?
最简单的方法:
self.Age = ko.observable().extend(
number:
params: true,
message: 'Age - please enter a number'
,
required:
params: true,
message: 'Age is required'
);
如果这样做是合理的,您可能需要投资于扩展默认消息传递行为,否则为每个属性上的每个验证器指定消息会更容易。
【讨论】:
我认为这确实适用于简单的视图模型,其中字段是静态的,但我实际上正在编写一个框架,其中包含各种字段的元数据,包括显示/友好名称。因此,我确实需要在框架级别上基于此元数据将 ko.extenders 应用于我的(动态)对象,并且为避免重复,这需要尽可能通用。因此,我可能会根据 GôTô 的想法选择一些东西,但还会将友好名称添加到错误集合中。 @philicomus 您最初的问题是差不多一年前的 - 您在此期间在做什么? 服务器验证一件事! :) 我将服务器上的验证视为最高优先级,并将附加的客户端验证视为一项不错的选择。由于这是我一直在开发的框架,因此我一直致力于使用该框架实现新应用程序。【参考方案5】:这种开销最小的方法非常适合我的需求:
ko.validation.rules["required"].message = "0 required";
用法:
self.driverName = ko.observable().extend( required: "Driver Name" );
渲染结果:
Driver Name required
注意:单步执行 knockout.validation.js 向我展示了将默认的 ko.validation.rules[] PRIOR 修改为任何 ko.observable().extend() 调用至关重要。
【讨论】:
【参考方案6】:虽然这不能回答这个问题的“友好”标签部分,也不会导致一系列验证错误,但它确实构建了一个对象,让您可以看到巨大的视图模型验证错误隐藏在哪里。这个问题提到了遍历视图模型来构建错误,所以我想我会在 Lodash 的帮助下分享我为此构建的递归函数。
function getErrors(koVm, maxDepth, currentDepth)
if ((currentDepth || 0) < (maxDepth || 5))
var obj = _.pickBy(_.mapValues(koVm, function(value)
if (value)
if (_.isFunction(value.error))
return value.error();
return getErrors(value, maxDepth, (currentDepth || 0) + 1);
return null;
));
return _.keysIn(obj).length ? obj : null;
return null;
它不适合向用户显示错误(除非您将构造的对象展平),但在调试和尝试找出大型模型的哪些部分无效时,它很有帮助。
【讨论】:
以上是关于如何将 ko.validation 错误与相关的视图模型字段名称联系在一起的主要内容,如果未能解决你的问题,请参考以下文章
KnockOut.js 验证始终为真/errors.length = 0
insertValidationMessage 敲除不起作用
存储过程是不是可以调用截断 veiw 表并将数据输入到 MySql 中的视图表中[关闭]