Knockout JS:使用改变DOM的旧验证代码
Knockout JS: Working with old validation code that changes the DOM
见底部编辑
我的公司有一个巨大的代码库,我们想开始更有效地使用knockout。但是,我们已经有了处理客户端验证的所有方面的验证代码。它使用jQuery来显示验证错误消息并清理用户输入。
例如,如果我添加类"validate-range"到输入,它将使用jQuery change/focusout事件来跟踪更改,然后如果一个值超出了范围,它将使用$(input).val()将其替换为最小/最大值。由于此验证代码以编程方式进行更改,因此当进行此类更改时,我的knockout视图模型将不会更新。
此验证代码在系统中无处不在,目前无法替换,因此为了使用knockout,我必须使其与此代码一起工作。到目前为止,我所尝试的是创建一个自定义值绑定,它添加了一个额外的更改事件处理程序,用于在验证代码更改输入值时更新视图模型。
这在所有情况下都出奇地好,除了在foreach绑定中(我想这与使用模板/with绑定是一样的)。我的change事件处理程序不会在foreach中使用自定义值绑定的任何输入上触发,即使每次可观察数组发生变化时,自定义绑定都会被重新应用到foreach中的所有输入上。
我希望有人以前处理过这个问题,不得不与现有的改变DOM值的javascript代码进行淘汰工作,因此不更新视图模型。如有任何帮助,不胜感激。
用于自定义绑定、创建视图模型和旧验证代码的Javascript代码:
// custom value binding for amounts
ko.bindingHandlers.amountValue = {
init: function (element, valueAccessor) {
var underlyingObservable = valueAccessor(),
interceptor = ko.computed({
read: function () {
var value = underlyingObservable();
return formatAmount(value);
},
write: function (newValue) {
var current = underlyingObservable(),
valueToWrite = parseAmount(newValue);
if (valueToWrite !== current)
underlyingObservable(valueToWrite);
else if (newValue !== current.toString())
underlyingObservable.valueHasMutated();
}
});
// i apply a change event handler when applying the bindings which calls the write function of the interceptor.
// the intention is to have the change handler be called anytime the old validation code changes an input box's value via
// $(input).val("new value"); In the case of the foreach binding, whenever the observable array changes, and the table rows
// are re-rendered, this code does get ran when re-applying the bindings, however the change handler doesn't get called when values are changed.
ko.applyBindingsToNode(element, { value: interceptor, event: { change: function () { interceptor($(element).val()); } } });
}
};
// view model creation
// auto create ko view model from json sent from server
$(function () {
viewModel = ko.mapping.fromJS(jsonModel);
ko.applyBindings(viewModel);
});
// old validation code
$(document).on("focusout", ".validate-range", function () {
var $element = $(this),
val = $element.val(),
min = $element.attr("data-val-range-min"),
max = $element.attr("data-val-range-max");
if (val < min)
// my change handler from custom binding doesn't fire after this to update view model
$element.val(min);
if (val > max)
// my change handler from custom binding doesn't fire after this to update view model
$element.val(max);
// more code to show error message
});
在foreach绑定中使用自定义绑定的HTML代码:
<table>
<thead>
<tr>
<td>Payment Amount</td>
</tr>
</thead>
<tbody data-bind="foreach: Payments">
<tr>
<td><input type="text" class="validate-range" data-val-range-min="0" data-val-range-max="9999999" data-bind="amountValue: Amount" /></td>
</tr>
</tbody>
</table>
因此,在上面的示例中,如果我在金额文本框中输入"-155",我的自定义绑定将运行并将视图模型金额设置为-155。然后运行旧的验证并使用$(input).val(0)将文本框的值重新设置为"0"。我的视图模型此时没有更新,仍然反映-155值。我的自定义绑定的更改事件处理程序应该运行以将视图模型更新为0,但它没有。
编辑:正如答案中指出的那样,.val()不会触发任何更改事件。我添加的更改事件处理程序没有做任何事情。当验证代码更改foreach绑定之外的值时,视图模型被更新的原因是因为我们在javascript代码的其他地方有逻辑,使用blur事件手动触发更改事件,这反过来触发我的自定义绑定来运行和更新视图模型。这个模糊事件处理程序直接绑定到文本框,而不是委托,所以它适用于页面第一次呈现时存在的文本框,但不适用于由foreach绑定动态插入的文本框。
现在,我只是将这个逻辑更改为委派文档中的事件,因此它将包括动态插入的文本框,并且看起来工作得很好。我希望将来能想出一个更好的解决方案。
调用$(element).val("some value");
不触发变更事件。
您需要做:$(element).val("some value").change();
- 为什么此验证代码不起作用
- javascript验证代码不起作用
- 如何将我自己的验证代码添加到MooTools的lightface表单中
- 我将如何形成正确的 POST 请求以LinkedIn将临时身份验证代码交换为访问令牌,SSL3 是原因吗?
- JQuery 验证代码不允许删除输入的文本
- 用于 excel 文件上传 jQuery 的正则表达式验证代码
- 验证代码不起作用,直接重定向到操作路径
- 来自电子邮件的身份验证代码
- 此HTTP Get-Basic身份验证代码有什么问题
- 为什么我的验证代码不起作用
- 除非重新加载页面,否则Javascript会被困在验证代码的错误警报中
- Javascript验证代码,以确保至少标记了一个复选框
- 使用ajax更改验证代码
- 服务器级SDK,可以加载PDF文件并执行计算和验证代码片段
- JavaScript表单验证代码错误
- 验证代码问题
- knockoutJS中的验证代码不起作用
- 我应该在asp MVC中使用不显眼的javascript而不是编写自己的验证代码吗?
- 在DOM中插入jQuery验证代码
- JavaScript表单验证代码没有给出期望的结果