2

私は KO bindingHandler で jquery アコーディオンを使用しています。アプリの要件によって ajax を使用して、アコーディオン UI で使用される DOM を設定する必要があります。

this.faqList = ko.observableArray();
$.ajax({
  url: 'getFaqs'
}).done(function( data ) {
  that.faqList(data);
});

私の bindingHandler は次のように単純でなければなりません

ko.bindingHandlers.koAccordion = {
  init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    $(element).accordion(valueAccessor());

  },
  update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
      $(element).accordion(valueAccessor());
  }
};

update メソッドは observableArray (faqList) が変更されたときに呼び出されますが、その時点で UI アコーディオンは DOM 構造が既に設定されている必要がありますが、これは true ではなく、update メソッドが呼び出された後に KO が作成されるようです。DOM 構造に新しいコンテンツが取り込まれた後、更新の呼び出しを行うにはどうすればよいですか?

これがデフォルトの DOM です。

<ul class="question-list" data-bind="koAccordion: {
          active: false,
          autoHeight: false, 
          collapsible: true}">
  <!-- ko foreach: faqList -->
    <li>
      <div class="header">
        <span class="rigth-arrow"></span>
        <a href="#" data-bind="text: title"></a>
      </div>
      <div class="content">
        <h2 data-bind="text: title"></h2>
        <div data-bind="text: content"></div>
      </div>
    </li>
  <!-- /ko -->
  </ul>

コードペン

4

2 に答える 2

3

koAccordion.updateそのバインディング値を更新しないため、役に立ちません。マークアップでは静的であり、監視対象は含まれていません。foreachバインディングはafterRender、あなたの目的のためにコールバックを提供します:

var vm = function() {
    // ...
    this.initAccordion = function(element) {
        $(element).accordion(accordionOptions);
    };
};


<!-- ko foreach: { data: faqList, afterRender: initAccordion } -->

ただし、この場合、バインディング値からアコーディオン オプションを移動する必要があります。カスタム バインディングを使用することを主張する場合、これを行う 1 つの方法は、作業をバインディングに委任し、途中でバインディング値にforeach挿入することです。afterRender

ko.bindingHandlers.koAccordion = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel,
                   bindingContext) {
        var newValue = ko.computed(function() {
            var value = ko.unwrap(valueAccessor());
            value.afterRender = function(element) {
                $(element).accordion(value);
            };
            return value;
        });
        return ko.bindingHandlers.foreach.init(element, newValue,
            allBindingsAccessor, viewModel, bindingContext);
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel,
                     bindingContext) {
        return ko.bindingHandlers.foreach.update(element, valueAccessor,
            allBindingsAccessor, viewModel, bindingContext);
    }
};

次のように使用します。

<ul class="question-list" data-bind="koAccordion: {
      data: faqList,
      active: false,
      autoHeight: false, 
      collapsible: true }">
   <li>...bindings...</li>
</ul>

投稿のページからフォークしたデモ ページを参照してください: http://codepen.io/anon/pen/IJpuj

于 2013-08-07T05:19:42.040 に答える
1
This is my final code
ko.bindingHandlers.koAccordion = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
  var newValue = ko.computed(function() {
    var value = ko.unwrap(valueAccessor());
    value.afterRender = function(renderedElement, loopEntryObject) {
      if ( loopEntryObject == value.data()[value.data().length - 1] ) {
        if ($(element).data('accordion')) {
          $(element).accordion('destroy');
        }
        $(element).accordion(value);
      }
    };
    return value;
  });
  return ko.bindingHandlers.foreach.init(element, newValue, allBindingsAccessor, viewModel, bindingContext);
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
  return ko.bindingHandlers.foreach.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
}
于 2013-08-07T18:37:46.377 に答える