7

我正在使用 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()));

html

<ul data-bind='foreach: model().errors' class="message">
    <li>
           <span data-bind='text:  $data'></span>
    </li>
</ul>

非常感谢

4

6 回答 6

7

您可以执行以下操作:

  • 添加一个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为可观察对象,因为我猜它不会被更新,但可以这样做。

演示

于 2014-06-20T13:43:16.923 回答
7

您可以对任何变量使用自定义验证消息。

emailAddress: ko.observable().extend({
    required: { message: 'Email Address: Required field.' }
}),
于 2013-08-08T18:46:30.577 回答
3

我发现这很好用 - 在控制台中输入 (F12):

for(var propertyName in PersonModel()) {
  console.log(ko.validation.group(PersonModel()[propertyName])())
}

这会给你类似的东西:

[]
[]
[]
[This field is required.]
[]
[]

然后,您可以将问题字段绑定到模型中的属性。在此示例中,问题将出在第 4 个属性上。

我希望这可以帮助别人。

于 2016-01-30T19:53:50.670 回答
2

不幸的是,您需要为每个验证者指定消息,除非您执行完全自定义的操作,例如 GôTô 建议的。

想一想……您还没有为您的字段指定显示名称,那么 ko 验证应该如何知道验证错误消息的字段名称?

最简单的方法:

self.Age = ko.observable().extend({ 
   number: {
      params: true,
      message: 'Age - please enter a number'
   },
   required: { 
      params: true,
      message: 'Age is required'
   }
});

如果这样做是合理的,您可能需要投资扩展默认消息传递行为,否则更容易为每个属性上的每个验证器指定消息。

于 2014-06-24T06:42:40.583 回答
1

虽然这不能回答这个问题的“友好”标签部分,也不会导致一系列验证错误,但它确实构建了一个对象,让您看到巨大的视图模型验证错误隐藏在哪里。问题提到遍历视图模型以构建错误,所以我想我会在 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;
}

向用户显示错误并不是很好(除非您将构造的对象展平),但在调试和试图找出巨大模型的哪些部分无效时,它是一个很大的帮助。

于 2019-02-15T23:29:17.813 回答
1

这种最小的开销方法非常适合我的需求:

ko.validation.rules["required"].message = "{0} required";

用法:

self.driverName = ko.observable().extend({ required: "Driver Name" });

渲染结果:

Driver Name required

注意:单步执行 knockout.validation.js 向我展示了在任何ko.observable ().extend() 调用之前修改默认的 ko.validation.rules[] 至关重要。

于 2016-03-29T17:41:58.600 回答