2

我有一个绑定到ko.observableArray.

我必须确保文本框的值不能为空,如果它是空白的,我会使用 jQuery 将值设置为 0blur()

问题是使用 jQuery 完成的值更改没有被淘汰注册。

如何观察模型中的值变化?

请参阅我的简化小提琴以了解要点 - 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());
4

3 回答 3

15

你需要两件事:

  1. 使用 jQuery 更改元素的值后,需要让 Knockout 知道更新模型。您可以通过触发change事件来做到这一点:

    $('input').val(0).trigger('change');
    
  2. 为了让 Knockout(3.1.0 之前)响应 jQuery 事件,它需要知道您正在使用 jQuery。为此,您必须在 Knockout 之前在文档中包含 jQuery。

这是你对这两个更新的小提琴:http: //jsfiddle.net/mbest/k45gd/2/

于 2013-04-06T01:53:24.243 回答
5

在您提供的示例中,您正在使用以下代码更新输入框:

this.setAgeExternally = function(){
    $('input').val(0);
}

考虑到输入绑定到年龄属性,这样做会更简单:

this.setAgeExternally = function(){
  this.age(0);
}

然而,即使这样也不是真的需要,因为年龄属性暴露在你的视图模型上。所以外部代码可以做到这一点,而 setAgeExternally 方法并不是真正需要的:

model.age(0);

让我们回到您最初的问题 - 您描述但未发布代码的问题。您提到您有一个绑定到可观察数组的输入框列表。

使用 observable 数组时需要注意一个有趣的问题:

http://knockoutjs.com/documentation/observableArrays.html的文档中:

关键点:一个 observableArray 跟踪数组中有哪些对象,而不是那些对象的状态

简单地将一个对象放入 observableArray 并不能使该对象的所有属性本身都可观察。当然,如果您愿意,您可以使这些属性可观察,但这是一个独立的选择。observableArray 只跟踪它持有的对象,并在添加或删除对象时通知侦听器。

鉴于您列出的要求,根本不需要 jQuery。您可以尝试以下三部分解决方案:

  1. 让你的 observableArray 包含 observables。所以你最终会得到类似的东西:

    var model = function() {
      this.ages = ko.observableArray([
        {age: ko.observable(13)},
        {age: ko.observable(18)},
        {age: ko.observable(16)},
        {age: ko.observable(13)}
      ]);
    };
    
  2. 接下来,创建一个敲除扩展器,如果为空,它会自动重置为 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;
    };
    
  3. 将扩展器应用于数组中的可观察对象

    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"})
      ]);
    };
    

工作小提琴:http: //jsfiddle.net/tlarson/GF3Xe/

于 2013-04-08T05:11:39.280 回答
0

使用迈克尔最佳建议:

这是对我有用的代码:

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,节省了我的时间... :)

于 2014-04-25T19:05:58.843 回答