Select2 与 Knockout.js 初始值

Posted

技术标签:

【中文标题】Select2 与 Knockout.js 初始值【英文标题】:Select2 with Knockout.js inital value 【发布时间】:2014-08-01 22:17:34 【问题描述】:

我将 Select2 与 knockout.js 一起使用。

但是控件没有正确显示初始值。看来选择功能没有提出

我修改了一个现有的 jsbin 来演示我的问题。

http://jsbin.com/xufovura/6/edit

绑定:

<div data-bind="value: selectedState, select2:  data: states, placeholder: 'Select a State', formatResult: format ,initSelection: initSelect" class="select2" style="width: 200px"></div>

自定义绑定的一部分(jsbin中的完整代码):

ko.bindingHandlers.select2 = 
    init: function(el, valueAccessor, allBindingsAccessor, viewModel) 
      ko.utils.domNodeDisposal.addDisposeCallback(el, function() 
    $(el).select2('destroy');
);

            var allBindings = allBindingsAccessor(),
            select2 = ko.utils.unwrapObservable(allBindings.select2);

      $(el).select2(select2);

    
;

 function initSelect(element, callback) 
   console.log("initSelect");
          var selectedItems = $.grep(this.states, function (e)  return e.id == element.id; );

           console.log(element);


            callback(selectedItems[0]);
        

【问题讨论】:

你的initSelect函数没有被调用的原因是select2认为你的占位符被选中了。您需要使用输入元素,而不是 div,因为 select2 将尝试通过调用 jQuery 的 val 函数来读取元素的当前“值”。 div 元素将始终返回 "" 【参考方案1】:

未调用您的 initSelect 函数的原因是 Select2 认为您的占位符已被选中。 Select2 读取$(element).val(),如果结果为假,则认为占位符被选中。

您的 div 元素将始终为 val() 结果返回 ""。

您应该将 div 元素切换为输入元素,但是当我在您的 jsBin 中执行此操作时,我发现输入的值没有被敲除初始化。这是值绑定的时间问题,因为在调用 select2 绑定的 init 函数时尚未调用值绑定的更新函数。

Knockout 首先调用所有的 init 函数,然后是 update 函数。

不使用选择元素时,Select2 不能很好地与 Knockout 配合使用!!

一个快速而肮脏的解决方案是确保在调用 select2 插件之前设置元素的值。

init: function(el, valueAccessor, allBindingsAccessor, viewModel) 
  ko.utils.domNodeDisposal.addDisposeCallback(el, function() 
    $(el).select2('destroy');
  );

  var allBindings = allBindingsAccessor(),
  select2 = ko.utils.unwrapObservable(allBindings.select2);

  // Ensure the input's value is set before calling select2
  $(el).val(allBindings.value());
  $(el).select2(select2);      

您也不再需要 initSelected 选项,事实上,由于$.grep(this.states, ...) "this" 导致您在 jsBin 中失败,此时并没有引用视图模型。

您还需要注意 allBindingsAccessor 在迁移到 Knockout 3.x 时会发生变化


更长更完整的答案涉及为各种 select2 事件设置处理程序,以及手动订阅支持值以在绑定的更新方法需要时协调对 $(el).select2('data', ...) 的手动调用。

如果您将后备存储更改为一个对象而不仅仅是一个字符串值(即存储实际的“状态”对象,而不仅仅是它的 id),那么这种方法也将是必需的

【讨论】:

您好,您所说的“allBindingsAccessor 在迁移到 Knockout 3.x 时发生变化”到底是什么意思,我需要改变什么? 在 KO 3.x 中,元素上的各个绑定现在仅在它们各自的依赖关系发生变化时才会更新。在 KO 2.x 中,如果任何绑定依赖项更新,则元素上的所有绑定都会更新。这导致了 allBindingAccessor 参数的一个小的 API 更改。 allBindingAccessor().value 现在是 allBindingsAccessor.get('value')

以上是关于Select2 与 Knockout.js 初始值的主要内容,如果未能解决你的问题,请参考以下文章

使用 Knockout.js 对 Select2 的标记支持

带有自定义模板的 Knockout.Js 中的 Select2

Knockout.js Select2 绑定。将 Select2 升级到 v4 后损坏

使用 knockout.js 和 select2 级联下拉菜单

Knockout/Select2:触发 select2 根据可观察的选项更新进行更新

选择了 Knockout.js 下拉绑定