【问题标题】:KnockoutJS Validation with dynamic observables使用动态可观察对象进行 KnockoutJS 验证
【发布时间】:2014-01-02 10:17:33
【问题描述】:

我正在使用这个插件https://github.com/ericmbarnard/Knockout-Validation,我正在尝试验证一个动态加载的对象。

Javascript:

function VM() {
    var self = this;
    // This is a static observable, just to ensure that basic validation works fine.
    self.static = ko.observable();
    self.static.extend({required: true});

    // This is the observable that will be updated to my model instance.
    self.person = ko.observable({});

    // This is an handler for manual trigger.
    // I'm not even sure this is needed.
    self.a = function(){
        self.errors.showAllMessages();
        self.staticErrors.showAllMessages();
    }

    // Here i'm loading current person from somewhere, i.e. a rest service.
    self.load = function() {
        // Update observable
        self.person(new Model());

        // Define validation rules
        self.person().name.extend({required: true});
        self.person().email.extend({required: true});

        // Set person data
        self.person().name('Long');
        self.person().email('John'); 

        // Set validators
        self.errors = ko.validation.group(self.person);
        self.staticErrors = ko.validation.group(self.static);
    }
}

// Just a test model.
function Model() {
    this.name = ko.observable();
    this.email = ko.observable();
}

ko.validation.init();
var vm = new VM();
ko.applyBindings(vm);

标记

<ul>
    <li>1. Hit "Load"</li>
    <li>2. Hit "Show errors", or maunally change input data.</li>
</ul>
<button data-bind='click: load'>Load</button>
<br/>

<h1>This is working properly.</h1>
<input type='text' data-bind='value: static' />
<br/>

<h1>This is not working.</h1>
<input type='text' data-bind='value: person().name' />
<input type='text' data-bind='value: person().email' />
<br/>
<button data-bind='click: a'>Show errors</button>

小提琴 http://jsfiddle.net/qGzfr/

我该如何进行这项工作?

【问题讨论】:

  • 您尝试过我提出的解决方案了吗?它们对您有用吗,还是您需要进一步的帮助?
  • @nemesv 我认为您的解决方案都非常有效。我只是在等待接受,因为有人为此开过赏金
  • 哦,我没有注意到你不是盯着赏金的人......所以@artlung 你有没有尝试过我提出的解决方案?它们对您有用吗(它们在 brazorf 中效果很好),还是您需要进一步的帮助?
  • @nemesv 我提供赏金只是因为我认为这个问题需要更多关注。我最近为自己的问题使用了赏金并得到了很大的帮助,我想帮助一个 knockout.js 问题。我会将赏金应用于 OP 想要的任何帖子或任何获得最多票的问题。
  • 你希望得到哪个答案?

标签: javascript knockout.js knockout-validation


【解决方案1】:

只有在 Knockout 解析绑定时您的属性已验证时,验证插件才会应用于您的绑定。

换句话说:您不能在属性绑定到 UI 之后向属性添加验证。

在您的示例中,您在 self.person = ko.observable({}); 中使用空对象作为默认值,因此当 Knockout 执行 data-bind='value: person().name' 表达式时,您没有 name 属性,因此即使您稍后将 name 属性添加到您的对象。

在您的示例中,您可以通过更改 Model 构造函数以包含验证规则来解决此问题:

function Model() {
    this.name = ko.observable().extend({required: true});
    this.email = ko.observable().extend({required: true});
}

并使用一个空的Model 对象作为默认人:

self.person = ko.observable(new Model());

并且在调用Load 时不要替换person 对象,而是更新其属性:

self.load = function() {

    // Set person data
    self.person().name('Long');
    self.person().email('John'); 
}

演示JSFiddle.

注意:如果您像 self.person(new Model()); 这样替换整个对象,Knockout 并不总是能很好地处理,因此最好只更新属性而不丢弃整个对象。

另一种解决方案是使用with 绑定,因为在with 绑定内部,如果绑定属性发生更改,KO 将重新评估绑定。

所以改变你的看法:

<!-- ko with: person -->
    <input type='text' data-bind='value: name' />
    <input type='text' data-bind='value: email' />
<!-- /ko -->

在这种情况下,您需要使用null 作为默认person

self.person = ko.observable();

在您的Load 中,您需要在分配person 属性之前添加验证,以便在 KO 应用绑定时,您的属性具有验证:

self.load = function() {

    var model = new Model()

    model.name.extend({required: true});
    model.email.extend({required: true});

    self.person(model);

    // Set person data
    self.person().name('Long');
    self.person().email('John'); 
}

演示JSFiddle.

【讨论】:

  • "在属性绑定到 UI 后,您无法向属性添加验证。"你能分享一下你是怎么得出这个结论的吗?
  • @ebramtharwat 来自插件的源代码...验证插件正在修改 valuechecked 投标,并在 init 函数中检查绑定属性是否可验证或不。如果属性在init 中不可验证,则验证插件不再关心该属性:github.com/Knockout-Contrib/Knockout-Validation/blob/master/Src/…
  • 如果你做value: person().name并且person的值被替换,绑定将被重新评估。但是,它不会再次调用 init;刚刚更新。
【解决方案2】:

我能够让它工作,这是所需的更改:

<head>                                                                           
    <script type="text/javascript" src ="knockout-2.3.0.js"></script>            
    <script type="text/javascript" src ="knockout.validation.min.js"></script>   
</head>                                                                          

<body>                                                                           
    <!-- no changes -->                                                          

    <script>                                                                     
        function VM() { ... }                           

        function Model() { ... }                        

        // ko.validation.init();                                                 
        var vm = new VM();                        
        ko.applyBindings(vm);                                                    

    </script>                                                                    
</body> 

做了什么?

  • 包括 KnockoutJS 和验证插件。
  • 在添加元素后绑定。请记住,HTML 页面是从上到下解析的。

你怎么知道?在控制台中出现了这个错误:

无法读取 null 的属性“nodetype”

无法调用未定义的方法“组”

【讨论】:

  • 呃,你的测试代码可能有问题,我的没有这样的错误
  • 我没有使用 JSFiddle,所以我指出可能会弹出哪些错误。面对类似问题的其他任何人都应该留意的那种事情(气味)。无论如何,你能让它正常工作吗?
猜你喜欢
  • 2013-10-01
  • 2017-10-09
  • 2012-04-20
  • 2017-11-25
  • 2012-06-13
  • 1970-01-01
  • 2015-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多