私はこの問題を、私が使い始めたソリューションの新しいテイクで更新すると思いました。以前はRP Niemeyerのフィドルhttp://jsfiddle.net/rniemeyer/dsKbH/を、KO observableArrayにバインドされたjQuery UIタブを動的に追加/削除するための基礎として使用していました。
私は、A)setTimeout()延期、およびB)アップデートがトリガーされるたびに、タブウィジェットを破棄して再作成することに関連して、アプリ内のいくつかの問題に対して立ち上がりました。だから私はこれらの問題を避ける別のアプローチを思いついた、そしてIMHOはよりエレガントなテクニックです。
http://jsfiddle.net/LatencyMachine/XJPJZ/
キーアイデアは、「タブパネル」と呼ばれる非常に単純なカスタム結合し、あなたのタブパネルのコンテンツのdiv要素に結合し、対応するウィジェットを導入することです。 KOがobservableArrayに基づいてこれらのdivを作成して削除すると、tabPanelバインディングはjQueryUI.tabsを "refresh"メソッドを使用して更新します。これは、コンテナ要素のバインディングで(そして適切なタイミングで)更新するためにタブを取得しようとするよりもずっとスムーズに動作します。フィドルから
関連するコード
/**
KO Binding handler for a tabPanel div. Use this on divs that can appear/disappear and/or have their id change
depending upon an observable, usually an observableArray.
*/
ko.bindingHandlers.tabPanel = {
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
$(element).tabPanel(ko.toJS(valueAccessor()));
}
};
/**
This widget facilitates jQuery UI tabs that appear and disappear dynamically, usually as a result of MVVM like Knockout
Whenever this widget is created, the containing jQuery UI 'tabs' widget is refreshed so that it picks up the new tab
or drops the removed one.
This also facilitates dealing with id rename 'ripple' that occurs whenever a tab is removed due to the splice of an
observable array.
*/
$.widget("bw.tabPanel", {
options: {
id: null
},
_create: function() {
this.element.hide();
this.tabsElement = this.element.closest(".ui-tabs");
if(this.options.id) {
this.element.attr({id: this.options.id});
}
this.refreshTabs();
},
_destroy: function() {
if(this.options.id) {
this.element.attr({id: ""});
}
this.refreshTabs();
},
_setOption: function(key, value) {
var previousValue = this.options[key];
if(previousValue == value) return;
this.options[key] = value;
switch(key) {
case "id":
this.element.attr({id: this.options.id});
this.refreshTabs();
break;
}
},
/**
Invoke refresh on the parent tab to let it know that something has changed.
This also preserves the active index by setting it back to what it was before the refresh, which
may correspond to a different tab after the refresh.
*/
refreshTabs: function() {
var previousActiveIndex = this.tabsElement.tabs("option", "active");
this.tabsElement.tabs("refresh");
this.tabsElement.tabs("option", "active", previousActiveIndex);
}
});