防止Knockout验证在初始加载时进行评估

9
我有一个简单的视图模型,包含几个必需属性...我希望每个输入框在对应属性无效时变为红色高亮显示,但是这种高亮只有在值改变或用户尝试保存/继续时才出现,而在页面初始加载时不显示...
目前在初始化加载时,它正在验证视图模型,因为我指定了data-bind="css: { error: name.isValid() == false }",但我不知道是否还有其他方式可以动态实现此操作(类似于jQuery非侵入式验证)。
var foo = { name: ko.observable().extend({required: true}) };

<div data-bind="css: { error: !name.isValid() }">
    <input type="text" data-bind="value: name" />
</div>

有关如何使这个工作的任何想法都将不胜感激...谢谢!

2个回答

5
更好的方法是配置knockout验证器,用validationElement类修饰元素。可以通过添加以下配置选项来完成此操作:
ko.validation.configure({ decorateElement: true });

点击此处查看演示jsfiddle。

****编辑,回应问题提问者的评论***

如果您需要装饰父元素,则更优雅且可重复使用的解决方案是将此自定义绑定应用于父元素。

Javascript

ko.bindingHandlers.parentvalElement = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var valueIsValid = valueAccessor().isValid();
        if(!valueIsValid && viewModel.isAnyMessageShown()) {
            $(element).addClass("parentError");
        }
        else {
            $(element).removeClass("parentError");
        }
    }
};

然后在你的HTML中应用绑定,如下所示:

<form data-bind='submit:OnSubmit'>
    <label data-bind='parentvalElement:name'>
        <span>Name</span>
        <input data-bind="value: name" />
    </label>
    <input type='submit' value='submit' />
<form>

请看 这个更新的 jsfiddle,以查看其实际效果。


抱歉,在简化我的示例时,我忘记了实际上是用“error”类装饰父div,而不是输入元素本身,因为还有其他子/同级元素也需要更改(例如:标签颜色和“*” span可见性),所以这对我不起作用,但是,我想我找到了一种方法来实现这个...基本上,在每个.extend()调用之后,我都会添加.isModified(false),然后在我的css绑定逻辑中检查.isModified()(请参见下文...)。 - Joshua Barker
我已经附加了一个更简单和可重用的解决方案来装饰父元素...试一下吧! - RodneyTrotter
我成功地让它工作了,而不必创建绑定处理程序... 我唯一不喜欢的部分是,我必须手动循环遍历视图模型属性并设置isModified(true),以便在我的外部对象调用.save()时,无效但未修改的字段将显示其错误状态。 - Joshua Barker

2
所以,这是我想出的解决方案:
var Foo = function()
{
    this.name = ko.observable().extend({required: true}).isModified(false);
    this.validate: function()
    {
        if (!this.isValid())
        {
            //... loop through all validated properties and set .isModified(true)
            return false;
        }
        return true;
    };
    ko.validation.group(foo);
};

var Bar = function()
{
   this.foo = new Foo();
   this.errors = ko.observableArray([]); //<-- displays errors for entire page
   this.save = function()
   {
       if (!this.foo.validate())
       {
          this.errors(ko.toJS(this.foo.errors()));
       }
   };
}

ko.applyBindings(new Bar());

这里是标记语言...

<div data-bind="with: foo">
    <div class="control-group"
         data-bind="css: { error: name.isModified() && !name.isValid() }">
        <label class="control-label">Name<span class="help-inline">*</span></label>
        <div class="controls">
            <input type="text" class="input-block-level" placeholder="Name"
                   data-bind="value: name, event: { blur: function () { name.isModified(true); }}" />
        </div>
    </div>

    <div class="alert alert-error"
         data-bind="visible: $parent.errors().length > 0">
        <h5>Errors!</h5>
        <ul data-bind="foreach: $parent.errors()">
            <li data-bind="text: $data"></li>
        </ul>
    </div>
</div>

<button type="submit" class="btn btn-primary" data-bind="click: save">Save</button>

这是CSS代码:

.error { color: Red; font-weight: bold; }
.help-inline { display: none; }
.error .help-inline { display: inline-block; }
.error input { border-color: Red; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接