I thought I was updating this question from a new perspective on the solution that I started using. I previously used the RP Niemeyer script http://jsfiddle.net/rniemeyer/dsKbH/ as the basis for dynamically adding / removing jQuery UI tabs tied to the KO observable array.
Over the past few months, I have encountered several problems in my application related to A) Deferring setTimeout (), and B) Destroy and recreate the tab widget every time the update starts. Therefore, I came up with a different approach that avoids these problems, and IMHO, is a more elegant method.
http://jsfiddle.net/LatencyMachine/XJPJZ/
The key idea is to introduce a very simple user binding called tabPanel and the corresponding widget that you link to your tabs in the contents of the tab. Because KO creates and deletes these divs based on your observable array, the tabPanel binding necessarily updates jQueryUI.tabs using the refresh method. I think this is much smoother than trying to get tabs for updates (and at the right time) in the bindings of container elements.
Corresponding code from the script
ko.bindingHandlers.tabPanel = { update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { $(element).tabPanel(ko.toJS(valueAccessor())); } }; $.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; } }, refreshTabs: function() { var previousActiveIndex = this.tabsElement.tabs("option", "active"); this.tabsElement.tabs("refresh"); this.tabsElement.tabs("option", "active", previousActiveIndex); } });
source share