Kendo-Knockout:嵌套绑定无法使用防护绑定

时间:2013-01-10 11:03:44

标签: knockout.js kendo-ui

我正在使用RPNiemeyer的kendo-knockout库。我有两个嵌套绑定。我在这里使用的是preventBindings技术:

http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html

我在父div上应用绑定,然后阻止嵌套div上的绑定。当我单击网格中的行时,我希望触发第二个绑定并弹出以打开但没有任何事情发生。示例代码类似于以下代码:Kendo-Knockout: widget observable is not filled with the actual widget

只有html不同(languageDetails div嵌套在languageList div中:

<div data-viewId="languageList">
  <div id="languageList" data-bind="with: viewModel">
    <div id="languageListGrid" data-bind="kendoGrid: { data: languageViewModels, columns: [ 
                { 
                    template: '<a href=\'\' data-bind=\'click: function() { onLanguageSelected(&quot;#=Language#&quot;) }\'>#=Language#</a>', 
                    field: 'Language', 
                    title: 'Language',
                    width: 50
                }

                ], 
            scrollable: false, sortable: true, pageable: false }, preventBinding: true"
    style="height: 380px"></div>
    <div data-bind="preventBinding: true">
      <div data-viewid="languageDetails">
        <div id="languageDetails" data-bind="with: viewModel" class="hidden">
          <form id="languageDetailsForm" action="" style="font-family: Trebuchet MS, Verdana, Helvetica, Sans-Serif;">
              <div data-bind="kendoWindow: {isOpen: isOpen, title:'Language', width: 400, height: 200, modal: true, widget: popUpWindow }">test
                  <button id="cancelLanguage" class="k-button" data-bind="click: cancelLanguage">Cancel</button>
              </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</div>

当我在languageList div上应用绑定时调试我的应用程序中的代码,然后单击该行打开弹出窗口,第二个绑定未应用,执行不会进入函数:

if (!elementIsBoundNew(element)) {
      var parentViewModel = {
        viewModel: viewModel
      };

这可能意味着第一个应用绑定已应用于两个嵌套的div,第二个防止绑定无效。这只是我的建议。

这是小提琴:

http://jsfiddle.net/PVMjy/4/

任何帮助将不胜感激。谢谢!

更新每个RP Niemeyer的评论:

您的解决方案适用于我在小提琴中提供的示例,但不适用于我的应用程序。在我的实际场景中,我使用网格中的selectedLanguage从现有视图模型列表中查找语言视图模型,并将其分配给selectedLanguageViewModel observable。换句话说,selectedLanguageViewModel永远不会为空。这是我真实应用程序中的代码:

LanguageListViewModel.prototype.onLanguageSelected = function (selectedLanguage) {
            var languageViewModel = getLanguageViewModel(selectedLanguage);
            self.selectedLanguageViewModel(languageViewModel);
            utils.applyBindings(self.selectedLanguageViewModel, languageDetailsElement);
            self.selectedLanguageViewModel().openPopUp(false);
            //createTreeView();
        };

我在这里做的是让它工作是保存我在数组中绑定的div的元素。然后,当我必须应用绑定时,我检查元素是否在数组中,如果不是,那么我应用绑定:

var applyedBindingsElements = [];

  var applyBindings = function (viewModel, elementId) {
    if($.inArray(elementId, applyedBindingsElements) == -1)
    {
      var element = $('div[data-viewId="' + elementId + '"]')[0];
      var parentViewModel = { viewModel: viewModel };
      ko.applyBindings(parentViewModel, element);

      applyedBindingsElements.push(elementId);
    }
  };

我未来的计划是使用languageList作为一个单独的组件,可以在同一页面上多次出现。然后,这个解决方案将无法工作,因为div elementIds我将两个组件绑定到,将具有相同的名称("languageList")。所以我将不得不考虑其他一些解决方案。但这是我将在不久的将来提出的另一个问题的主题,并将非常感谢您的反馈意见。谢谢!

在这个主题上解决我的解决方案:

http://jsfiddle.net/PVMjy/6/

1 个答案:

答案 0 :(得分:1)

问题是ko.dataFor搜索DOM以查找其值。因此,它实际上超出了跳过绑定的区域并找到了整体视图模型。因此,当您尝试打开弹出窗口时,您的防范是否已经应用了绑定。

我做了一些小改动以摆脱绑定检查,并在第一次单击按钮时将绑定应用于弹出区域。

删除已绑定的支票后,基本上只是这段代码:

self.onLanguageSelected = function (selectedLanguage) {
  if (!self.selectedLanguageViewModel()) {
      applyBindings(self.selectedLanguageViewModel, "languageDetails");
  }

  self.selectedLanguageViewModel(self.languageViewModels()[0]);
  self.selectedLanguageViewModel().openPopUp();
};

示例:http://jsfiddle.net/rniemeyer/8hzzn/

这对你有用吗?