我创建了一个演示我的问题的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());
答案 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;
};