Knockout选择和文本框共享绑定

时间:2013-07-31 07:42:27

标签: javascript data-binding knockout.js

我有一个页面,其中一个select和一个输入框绑定到相同的值。我们的想法是,通常会从select中选择一个值,但是,用户也应该能够在输入框中输入任意字符串。问题是,如果我输入select中不存在的内容,由于绑定,该值将设置为select中的第一项。

这是我想要实现的行为:

用户从选择

中选择值
  1. 值设置为选定项目。
  2. 使用所选值更新输入。
  3. 用户在输入中输入文字

    1. 值设置为输入文本。
    2. 选择不会更改,除非值包含在可用值的集合中。
    3. 换句话说,我想要的是最后一次更改的控件是有效的值。但是,只要给定值对该控件有效,我也希望两个控件都是最新的

      我的代码如下所示:

      JS

      var viewModel = { Value: ko.observable('1'), Set: ['1', '2', '3'] };
      ko.applyBindings(viewModel);
      

      HTML

      <!-- ko if: Set.length > 1 || (Set.length > 0 && Set[0] != '') -->
      <select type="text" class="form-control input-small" data-bind="options: Set, value: Value">
      </select>
      <!-- /ko -->
      
      <input class="form-control input-small" data-bind="value: Value" style="margin-top: 5px;" />
      

      这是一个显示代码当前工作方式的jsfiddle:http://jsfiddle.net/b2RwG/

      [编辑]
      我找到了一个有效的解决方案(http://jsfiddle.net/b2RwG/2/),但它真的不太漂亮,必须有更好的方法来解决这个问题。

2 个答案:

答案 0 :(得分:1)

如您所见,我添加了一个绑定到文本输入的inputValue observable。 我还添加了一个计算名为virtualSet,其中包含原始项和新项(来自文本输入)。 我输入inputValue所以当你输入时会自动设置选择。

var viewModel = {    
    inputValue: ko.observable('1'),
    Value: ko.observable('1'),
    Set: ['1', '2', '3']    
};
viewModel.virtualSet = ko.computed({
    read: function () {
        var vs = this.Set.slice(0);
        if (this.inputValue() && this.inputValue().length)
             vs.unshift(this.inputValue());
        return vs;
    },
    owner: viewModel
});
viewModel.inputValue.subscribe(function (value) {
    viewModel.Value(value);
});

<强> See fiddle

我希望它有所帮助。

答案 1 :(得分:0)

您可以让select使用计算的observable,只有在值有意义时才会更新。

我做了一个例子,我在select中添加了一个标题。结果是它不会自动选择第一个值,而是在读取未包含在Set数组中的值时尝试设置未定义的值。

<select type="text" class="form-control input-small" data-bind="options: Set, value: SelectValue, optionsCaption: 'Other value'"></select>

为此,构造函数而不是对象文字将使其更容易,因为您可以通过Value引用访问self observable。

function ViewModel() { 
    var self=this; 
    this.Value = ko.observable('1'); 
    this.Set = ['1', '2', '3']; 
    this.SelectValue= ko.computed({
                 read: function() {
                     var val = self.Value(); 
                     return val; 
                 }, 
                 write: function(value) {
                     if(value) self.Value(value); 
                 }
    });
}

请参阅http://jsfiddle.net/b2RwG/4/