扩展器订单导致验证停止工作

时间:2014-01-29 19:52:12

标签: knockout.js knockout-validation

我创建了一个演示我的问题的JSFiddle:http://jsfiddle.net/jeffreyrswenson/hsW25/4/

我已经创建了一个自定义的Knockout扩展程序来修复我在序列化到JSON时遇到的问题。如果这个自定义扩展程序放在Knockout-Validation扩展程序之前,一切都按照我的预期运行。如果我在Knockout-Validation扩展器之后放置自定义扩展器,则验证将停止工作。

为什么会这样?将一个扩展器放在另一个扩展器之前是很容易的,但如果有人不知道这个问题,那么很难找出出现问题的原因。

HTML:

<label>First name:
    <input data-bind='value: firstName, valueUpdate: "afterkeydown"' />
</label>
<br/>
<label>Last name:
    <input data-bind='value: lastName, valueUpdate: "afterkeydown"' />
</label>
<br>
<pre data-bind="text: ko.toJSON($data,null,2)"></pre>

<br> <span data-bind='text: errors().length'></span> errors

JS:

ko.extenders.undefinedIfBlank = function (target, option) {
    if (option) {
        var result = ko.computed({
            read: target,
            write: function (newValue) {
                var current = target();
                if (newValue !== current) {                    
                    if (typeof newValue === "string" && newValue.length == 0) {
                        target.notifySubscribers(newValue);
                        target();
                    } else {               
                        target(newValue);
                    }
                } else {
                    var x = 1;
                }
            }
        }).extend({
            notify: 'always'
        });

        result(target());

        return result;
    }

    return target;
};

ko.validation.configure({
    decorateElement: true,
    registerExtenders: true,
    messagesOnModified: true,
    insertMessages: true,
    parseInputAttributes: true,
    messageTemplate: null
});

var viewModel = function () {
    this.firstName = ko.observable().extend({
        undefinedIfBlank: true
    }).extend({
        required: true
    });
    this.lastName = ko.observable().extend({
        undefinedIfBlank: true
    }).extend({
        required: true
    });
    this.errors = ko.validation.group(this);
};

ko.applyBindings(new viewModel());

1 个答案:

答案 0 :(得分:2)

您的自定义扩展程序会创建一个新的计算机,然后使用存储在其中的目标的展开值返回它。除了其值之外,这不会传递来自目标的任何其他现有属性。因此,如果您的扩展程序是第二次运行,它将清除任何以前的扩展名我不太了解扩展程序,以帮助您使您的级联友好(编辑:请参见底部的替代实现)。

    //Creates a new computed that doesn't carry over previous extensions
    var result = ko.computed({
        read: target,
        write: function (newValue) {
            var current = target();
            if (newValue !== current) {                    
                if (typeof newValue === "string" && newValue.length == 0) {
                    target.notifySubscribers(newValue);
                    target();
                } else {               
                    target(newValue);
                }
            } else {
                var x = 1;
            }
        }
    }).extend({
        notify: 'always'
    });

    //copies value but nothing else
    result(target());

    return result;

我确实注意到第二个问题。如果您键入某些文本,然后删除或输入零长度字符串,则不允许您删除最后一个字符。也许这就是你想要它做的事情?

    ko.extenders.undefinedIfBlank = function (target, option) {
        if (option) {
            var result = ko.computed({
                read: target,
                write: function (newValue) {
                    var current = target();
                    if (newValue !== current) {                    
                        if (typeof newValue === "string" && newValue.length == 0) {
                            //invoking target() alone doesn't really do anything
                            //target();
                            target(undefined); 
                            target.notifySubscribers(undefined);
                        } else {               
                            target(newValue);
                        }
                    } else {
                        var x = 1;
                    }
                }
            }).extend({
                notify: 'always'
            });

            result(target());

            return result;
        }

        return target;
    };

http://jsfiddle.net/rnkLb39b/2/

编辑:此处仍然不是专家,但这是您的扩展程序的实现。它不是创建一个新的计算机,而只是订阅现有的对象,从而扩展它而不是替换它。

    ko.extenders.undefinedIfBlank = function (target, option) {
        if (option) {
            var oldValue;
            target.subscribe(function(currentValue){
                oldValue = currentValue;
            }, null, 'beforeChange');

            target.subscribe(function (newValue) {
                    if (newValue !== oldValue) {                    
                        if (typeof newValue === "string" && newValue.length == 0) {
                            target(undefined);
                            target.notifySubscribers(undefined);
                        } else {            
                            target(newValue);
                        }
                    } else {
                        //do nothing?
                    }
            });

            return target;
        }

        return target;
    };

http://jsfiddle.net/13nugjca/