Knockout绑定不适用于jQueryUI对话

时间:2016-07-05 17:43:59

标签: jquery-ui knockout.js

我的viewModel有一个名为' Items'的数组。我想显示' Items'的内容。使用foreach绑定。当我使用常规HTML时,一切正常。但是不能使用我使用jQueryUI创建的对话框。

HTML:

<div id="skus0">
  <div id="skus1">
    <ul data-bind="foreach: Items">
      <li data-bind="text:Name"></li>
    </ul>
  </div>
  <input type="button" id="openQryItems" class="btn btn-info" value="Open" data-bind="click:openQueryItems" />
</div>  

JavaScript的:

// my view model
var viewModel = {
  Items: [{Name:'Soap'},{Name:'Toothpaste'}] 
};

// JS to configure dialogue
$("#skus1").dialog({
  autoOpen: false,
  width: 500,
  modal: true,
  buttons: {
    "OK": function () {
      $(this).dialog("close");
    },
    "Cancel": function () {
      $(this).dialog("close");
    }
  }
});

// for mapping my model using ko.mapping plugin
var zub = zub || {};
zub.initModel = function (model) {
  zub.cycleCountModel = ko.mapping.fromJS(model);
  zub.cycleCountModel.openQueryItems = function () {
    $("#skus1").dialog("open");
  }
  ko.applyBindings(zub.cycleCountModel, $("#skus0")[0]);
}

zub.initModel(viewModel);

我在这里创造了一个小提琴my fiddle

1 个答案:

答案 0 :(得分:2)

$.fn.dialog将元素从DOM中的位置移除并将其放入新容器中;这是它如何创建一个浮动窗口。发生这种情况的问题在于它破坏了数据绑定,因为对话框DOM不再嵌套在顶级数据绑定DOM中。

ko.applyBindings之后将对话框初始化移动到将使dialog在填充列表之后将东西从DOM 中拉出来。当然,这意味着在此之后,未来的更改仍然不会反映出来,如果您希望打开的对话框自动更改,这可能很重要。

如果您希望对话框内容完全动态,可以创建绑定处理程序;我们在项目中做到了这一点。以下是我们如何做到这一点的大致轮廓:

ko.bindingHandlers.dialog = {
  init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingCtx) {
    var bindingValues = valueAccessor();
    var hasAppliedBindings = false;
    var elem = $(element);
    var options = {
      id: ko.utils.unwrapObservable(bindingValues.id),
      title: ko.utils.unwrapObservable(bindingValues.title),
      // etc...
      onOpen: function () {
        if (!hasAppliedBindings) {
          hasAppliedBindings = true;
          var childCtx = bindingCtx.createChildContext(viewModel);
          ko.applyBindingsToDescendants(childCtx, element);
        }
      }
    };

    elem.dialog(options);
  }

  return { controlsDescendantBindings: true };
}

...我们这样使用:

<div data-bind="dialog: { title: 'some title', id: 'foo', ... }">
  <!-- dialog contents -->
</div>

return { controlsDescendantBindings: true }做的是确保外部绑定不会影响使用dialog绑定处理程序的任何内容。然后我们创建了我们自己的Knockout绑定&#34;岛&#34;在基于原始视图模型从DOM中拉出之后。

虽然在我们的项目中我们也使用了混合jQuery + Knockout,但我强烈建议你尽可能避免这种情况。我们不得不采用这么多黑客来维持这种类型的应用程序。你应该做的最好的事情是更喜欢Knockout绑定处理程序(我认为它现在有一个&#34;组件&#34;概念,我现在没有玩过),而不是DOM操作,以避免错误的UI管理。