Knockout.js多选和分隔字符串

时间:2016-05-27 13:26:28

标签: javascript knockout.js data-binding

只是发现淘汰赛,所以如果我错过了这里的话,请指出愚蠢。我目前有一个多重选择绑定到击倒中的一个observable。

<select class="form-control" id="SithSelect" data-bind="attr: { 'data-has-value': (Sith() ? true : false) }, selectedOptions: Sith() ? Sith().split('|') : '' " placeholder="The dark side" multiple>
    <option disabled></option>
    <option value="Darth Vader">Darth Vader</option>
    <option value="Darth Maul">Darth Maul</option>
    <option value="Darth Bane">Darth Bane</option>
</select>

其中“西斯”是一个可观察的字符串值。

当我在数据库中手动添加字符串值“Darth Vader | Darth Maul”并且值最终下降到客户端时,多选正确显示选择的两个值。

但是,如果我更改了值,那么如何将所选值组合回存储在observable中的管道分隔字符串?

根据我的尝试,我可以通过使用select绑定的可观察数组对其进行排序,然后在保存到数据库时重新构造管道分隔的字符串。当我查看代码时,这个解决方案闻起来有点滑稽,因为它感觉与单个select元素紧密耦合(这是页面上唯一一个使用来自DB的管道分隔字符串的文件)。

我是否遗漏了在多选和分隔字符串之间进行双向绑定的错误?相反,有没有办法与

相反
selectedOptions: Sith() ? Sith().split('|') : ''

将多个选定的选项分配回绑定中的可观察值?

更新:问题已缩小为:

是否有内置的东西可以放置在一个绑定中,可以处理计算值的读/写函数,这样我就可以内联编写它,而不必创建一个单独的计算可观察值? / p>

1 个答案:

答案 0 :(得分:1)

selectedOptions应该是数组或可观察的数组。 http://knockoutjs.com/documentation/selectedOptions-binding.html

当您向Sith传递一些数据时,Knockout无法知道如何将数据保存回Sith

您应该使用ko.observableArrayko.observable数组值。但是您需要同步字符串值和数组值。而不是手动支持两个订阅(str =&gt; arr,arr =&gt; str),您可以使用可写计算(http://knockoutjs.com/documentation/computed-writable.html):

<select data-bind="selectedOptions: sith">...</select>
vm.sithString = ko.observable('');
vm.sith = ko.computed({
  read: function() { return vm.sithString().split('|'); },
  write: function(arr) { vm.sithString(arr.join('|')); }
});

<强>更新

  

是否有内置的东西可以放置在一个绑定中,可以处理计算值的读/写函数,这样我就可以内联编写它,而不必创建一个单独的计算可观察值? / p>

这是MVVM中ViewModel的确切目的。你有模型,这是你的纯数据(嗯,你必须将它存储在observables中,但无论如何)。你有绑定,纯粹是UI的东西。并且它们之间有中介ViewModel来转换它们之间的数据和事件。此示例中的可写入计算表示ViewModel-Model关系。

可编写计算机比每个绑定的write / read函数更通用,更灵活。

更新2 好吧,selectedOptions并不是最简单的绑定。方法是将完全相同的计算机附加到元素并替换绑定函数中的valueAccessor。代码很简单,但需要了解bingings的工作原理:

var selectedOptions = ko.bindingHandlers['selectedOptions'];
ko.bindingHandlers['pipedOptions'] = {
  after: selectedOptions.after, /* ['options', 'foreach'] */
  init: function(el, va) {
    var obsv = va();

    var mediator = ko.computed({
      read: function() { return obsv().split('|'); },
      write: function(arr) { obsv(arr.join('|')); }
    });

    ko.utils.domData.set(el, 'pipedOptions.mediator', mediator);

    var args = [].slice.call(arguments);
    args[1] = function() { return mediator; };
    selectedOptions.init.apply(this, args);
  },
  update: function(el, va) {
    var mediator = ko.utils.domData.get(el, 'pipedOptions.mediator');
    var args = [].slice.call(arguments);
    args[1] = function() { return mediator; };
    selectedOptions.update.apply(this, args);
  }
};

如果您需要更复杂的行为,请查看组件。

相关问题