How to add or remove jQueryUI tabs using JS knockout?

I am trying to use knockout to add / remove jQueryUI tabs, but they are out of luck. My view model is an array of Effect objects. I would like the tab to be added / removed from the tab control, as objects are added / removed from the view model.

JSFiddle was launched here, and I updated it, which shows what I'm looking for. JSFiddle example

It will break when you try to add a tab. I think I need to combine the template binding with a new user binding that can destroy / recreate the tab control that I think. I would really appreciate any help. Thanks!

+6
source share
3 answers

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 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); } }); 
+3
source

You will most likely have to redisplay the tab interface every time the model changes.

Also, add a unique identifier to the <ul> tabs:

 <ul id="tabs"> 

Each time you change the model, call

 $("#tabs").tabs(); 

(I'm not sure how to fire the event with a knockout, but I'm sure this is in the documentation.)

0
source

I had a very similar problem. I have a deep view model diagram where the observed array of top-level child view models is presented as tabs, and each tab displays the markup for the grandson's data. I originally used jQuery UI tabs to tab my markup after Knockout built it.

I have functionality to add, delete and duplicate these models with viewing tabs / domain objects. With jQuery UI tabs, I had to call it destroy and then rebuild, and for cases like Duplicate, I had to first save the selected index, and then select this index + 1 after rest to select the newly created tab.

But now I’ve made more full use of MVVM as the driver of my user interface and completely cut out jQuery tabs and linked my own tab headers and tab content elements to the observable β€œisSelected” property on my Knockout view models. I found this to be a lot cleaner and gives me more flexibility, and the layout / CSS for the tabs turned out to be simple and elegant.

This Selected property also means that I can increase the efficiency of binding by specifying for each tab something like <div class="child" data-bind="if: isSelected"> . Previously (presumably) a knockout worked uselessly through all invisible tab bindings.

Here's how I'm trying to get closer to my user interface - avoid using the procedural user interface as much as possible in favor of using bindings.

0
source

Source: https://habr.com/ru/post/897113/


All Articles