【问题标题】:Making Knockout validations not fire on page load使敲除验证不会在页面加载时触发
【发布时间】:2014-12-09 02:15:40
【问题描述】:

我正在尝试使用 Knockout 实现验证,并尝试了来自 here 的“Bob”示例

<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

谢谢。

【问题讨论】:

  • 如果您使用链接页面中的ko.extenders.required,只需删除行//initial validation validate(target()); 行以禁用初始验证
  • @nemesv 这会删除初始验证,但现在即使用户离开文本框,验证也不会触发。
  • 你可以为它创建一个 jsfiddle 吗?
  • 请不要在没有将代码添加到问题中的情况下要求/添加小提琴,否则问题取决于异地链接(可能会腐烂)。
  • 您还需要使用 notify: 'always' 扩展器,因为否则当模糊事件触发时,剔除不会触发可观察对象的更改事件,因为没有 chagne,因此您的验证器不会触发`@ 987654323@

标签: validation knockout.js


【解决方案1】:

初始验证由以下行触发:

 validate(target());

注释掉。

但是现在,如果你进入空文本框,然后跳出它,没有任何变化:焦点时字段为空,模糊时字段为空。所以 observable 不会改变,订阅也不会被触发。

因此,您需要做的是在模糊时触发验证,而不仅仅是在更改时触发。您需要为绑定元素的 blur 事件订阅验证以进行额外验证。但这是不可能的,因为您无法访问可观察对象所绑定的元素。

就我能想到的解决方案而言,由于您只能访问 observable,因此您无法使用扩展器实现您想要的。

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

function(element, valueAccessor, allBindings)

我创建了一个required 自定义绑定处理程序的示例实现,您可以将其用作一个定位点。 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);

【讨论】:

  • 像这样 ,还是不行!
  • @Codehelp。很抱歉,这个答案不准确。现在我为你添加了额外的信息。
  • @Codehelp 添加了原始答案的替代方案
猜你喜欢
  • 1970-01-01
  • 2015-07-17
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
相关资源
最近更新 更多