在页面加载时不会触发Knockout验证

时间:2014-10-14 10:13:12

标签: validation knockout.js

我正在尝试使用Knockout实现验证,并尝试了#34; Bob"来自here

的示例
<p data-bind="css: { error: firstName.hasError }">
    <input data-bind='value: firstName, valueUpdate: "afterkeydown"' />
    <span data-bind='visible: firstName.hasError, text: firstName.validationMessage'> </span>
</p>
<p data-bind="css: { error: lastName.hasError }">
    <input data-bind='value: lastName, valueUpdate: "afterkeydown"' />
    <span data-bind='visible: lastName.hasError, text: lastName.validationMessage'> </span>
</p>

源代码:查看模型

ko.extenders.required = function(target, overrideMessage) {
    //add some sub-observables to our observable
    target.hasError = ko.observable();
    target.validationMessage = ko.observable();

    //define a function to do validation
    function validate(newValue) {
       target.hasError(newValue ? false : true);
       target.validationMessage(newValue ? "" : overrideMessage || "This field is required");
    }

    //initial validation
    validate(target());

    //validate whenever the value changes
    target.subscribe(validate);

    //return the original observable
    return target;
};

function AppViewModel(first, last) {
    this.firstName = ko.observable(first).extend({ required: "Please enter a first name" });
    this.lastName = ko.observable(last).extend({ required: "" });
}

ko.applyBindings(new AppViewModel("Bob","Smith"));

CSS:

.validationError{
        border:solid 1px red;
    }

在初始页面加载时,文本框中不会有任何数据。所以我删除了硬编码的名字。 现在,验证消息显示在页面加载上,而不是用户离开文本框时。 不知何故,KO在页面加载期间考虑文本框值已更改并触发验证代码。

如何阻止这种情况发生?

这是我试图尝试的用例。 我有两个文本框,一个需要显示没有消息的红色边框,另一个需要在验证时显示消息。

Sample here

感谢。

1 个答案:

答案 0 :(得分:0)

初始验证由以下行触发:

 validate(target());

评论出来。

但现在,如果您输入空文本框并跳出它,则没有任何变化:焦点时该字段为空,模糊时该字段为空。因此,observable不会改变,并且不会触发订阅。

因此,您需要做的是在模糊时触发验证,而不仅仅是在更改时。您需要将验证订阅到绑定元素的blur事件以进行其他验证。但这是不可能的,因为你不能接受observable所绑定的元素。

就我能想到的解决方案而言,由于您只能访问可观察对象,因此无法通过扩展器实现您想要的效果。

您需要创建一个custom binding,以便您访问该元素。在这种情况下,您可以访问元素,值访问器(相当于扩展器的target())以及元素中的所有其他绑定。这是自定义绑定更新功能的签名:

function(element, valueAccessor, allBindings)

我已经创建了一个required自定义绑定处理程序的示例实现,您可以将其用作satrting点。 Here is the fiddle,这是代码:

HTML:

<input type="text" data-bind="value: name, required: 'Name required'">
<span data-bind="visible: name.hasError, text: name.requiredMessage"></span>
<br/>
<input type="text" data-bind="value: age, required: 'Age required'">
<span data-bind="visible: age.hasError, text: age.requiredMessage"></span>

JavaScript的:

ko.bindingHandlers.required = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
        console.log('Init', element);
        var valueObs = allBindings.get('value');
        valueObs.hasError = ko.observable(false);
        valueObs.requiredMessage = ko.observable(ko.unwrap(valueAccessor()));
        valueObs.firstTime = true;
        $(element).blur(function() {
            console.log('Blur');
            valueObs.hasError(!valueObs());
        });
    },

    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever any observables/computeds that are accessed change
        // Update the DOM element based on the supplied values here.
        var valueObs = allBindings.get('value');
        console.log('value: ', valueObs());
        if (valueObs.firstTime) {
            valueObs.firstTime = false;
            return;
        }
        valueObs.hasError(!valueObs());
    }
};

var vm = {
    name: ko.observable(""),
    age: ko.observable("")
};

ko.applyBindings(vm);