我有一个绑定到ko.observableArray
的文本框列表。
我必须确保文本框值不能为空,如果在blur()
问题是,使用jQuery完成的值更改未被knockout注册。
如何观察模型中的值变化?
请参阅我的简化小提琴以获得重点 - http://jsfiddle.net/k45gd/1/
HTML
<input type="number" data-bind="value: age" />
<span data-bind="text: age"></span>
<button data-bind="click: setAgeExternally">I want the label to change to 0</button>
JS
var model = function() {
this.age = ko.observable(21);
//this code is outside of the model, this is oversimplification
this.setAgeExternally = function(){
$('input').val(0);
}
};
ko.applyBindings(new model());
答案 0 :(得分:14)
你需要两件事:
使用jQuery更改元素的值后,您需要让Knockout知道更新模型。您可以通过触发change
事件来执行此操作:
$('input').val(0).trigger('change');
对于Knockout(在3.1.0之前)响应jQuery事件,它需要知道你正在使用jQuery。要做到这一点,你必须在Knockout之前在你的文档中包含jQuery。
这是两个更新的小提琴:http://jsfiddle.net/mbest/k45gd/2/
答案 1 :(得分:5)
在您提供的示例中,您使用以下代码更新输入框:
this.setAgeExternally = function(){
$('input').val(0);
}
考虑到输入绑定到age属性,这样做会更简单:
this.setAgeExternally = function(){
this.age(0);
}
然而,即使这并不是真的需要,因为age属性在您的viewmodel上公开。所以外部代码可以这样做,并且真的不需要setAgeExternally方法:
model.age(0);
让我们回到原来的问题 - 您描述的问题,但不要发布代码。您提到您有一个绑定到可观察数组的输入框列表。
使用可观察数组时,您需要注意一个有趣的问题:
来自http://knockoutjs.com/documentation/observableArrays.html的文档:
关键点:observableArray跟踪数组中的对象, 不是那些对象的状态
简单地将一个对象放入一个observableArray并不能完全实现 该对象的属性本身是可观察的。当然可以 如果你愿意,可以观察这些属性,但那是一个 独立选择。 observableArray只跟踪它的对象 保持,并在添加或删除对象时通知侦听器。
根据您列出的要求,根本不需要jQuery。您可以尝试这个由三部分组成的解决方案:
使您的observableArray包含observable。所以你最终得到的结论是:
var model = function() {
this.ages = ko.observableArray([
{age: ko.observable(13)},
{age: ko.observable(18)},
{age: ko.observable(16)},
{age: ko.observable(13)}
]);
};
接下来,创建一个敲除扩展器,如果空白,则自动重置为0
ko.extenders.defaultIfBlank = function(target, defaultValue) {
var result = ko.computed({
read: target, //always return the original observables value
write: function(newValue) {
if (newValue == "") {
target(defaultValue);
} else {
target(newValue);
}
}
});
//initialize with current value to make sure it is not blank
result(target());
//return the new computed observable
return result;
};
将扩展器应用于数组中的observable
var model = function() {
this.ages = ko.observableArray([
ko.observable(13).extend({defaultIfBlank: "0"}),
ko.observable(18).extend({defaultIfBlank: "0"}),
ko.observable(16).extend({defaultIfBlank: "0"}),
ko.observable(13).extend({defaultIfBlank: "0"})
]);
};
答案 2 :(得分:0)
Michael Best建议:
这是对我有用的代码:
function insertControlsAtcaret(element, addControlText){
if (element.selectionStart || element.selectionStart == '0') {
//For browsers like Firefox and Webkit based
var startPos = element.selectionStart;
var endPos = element.selectionEnd;
var scrollTop = element.scrollTop;
element.value = element.value.substring(0, startPos) + addControlText + element.value.substring(endPos, element.value.length);
$(element).trigger("change");
element.focus();
element.selectionStart = startPos + addControlText.length;
element.selectionEnd = startPos + addControlText.length;
element.scrollTop = scrollTop;
} else {
element.value += addControlText;
$(element).trigger("change");
element.focus();
}
};
Thx MB,节省了我的时间......:)