如何使用knockout JS添加或删除jQueryUI选项卡?

时间:2011-09-11 21:36:09

标签: jquery jquery-ui knockout.js

我一直在尝试使用knockout添加/删除jQueryUI标签,但没有任何运气。 我的视图模型是一个Effect对象数组。我希望在视图模型中添加/删除对象时,从选项卡控件中添加/删除选项卡。

这是一个JSFiddle,有人开始,我更新了,显示了我想要做的事情 JSFiddle example

尝试添加标签时会中断。我想我需要结合模板绑定w /一个新的自定义绑定,可以破坏/重新创建我认为的选项卡控件。我非常感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:3)

我以为我会在我开始使用的解决方案上更新这个问题。我以前一直在使用RP Niemeyer的小提琴http://jsfiddle.net/rniemeyer/dsKbH/作为动态添加/删除绑定到KO observableArray的jQuery UI标签的基础。

在过去的几个月里,我遇到了与我的应用程序中的一些问题相关的问题:A)setTimeout()延迟,以及B)每次触发更新时销毁和重新创建选项卡小部件。所以我提出了一种避免这些问题的不同方法,恕我直言,这是一种更优雅的技术。

http://jsfiddle.net/LatencyMachine/XJPJZ/

关键的想法是引入一个非常简单的自定义绑定,名为" tabPanel"以及绑定到选项卡面板内容div的相应窗口小部件。当KO根据你的observableArray创建并删除这些div时,tabPanel绑定确保使用它更新jQueryUI.tabs"刷新"方法。我认为这比使用标签在容器元素的绑定中更新(并在适当的时候)更加顺畅。

来自小提琴的相关代码

/**
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);        
    }
});

答案 1 :(得分:0)

每次模型更改时,您很可能必须重新渲染选项卡界面。

另外,在标签<ul>中添加唯一ID:

<ul id="tabs">

每次模特改变时,请致电

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

(我不确定如何使用Knockout发起一个事件,但我确定它在文档中。)

答案 2 :(得分:0)

我有一个非常类似的问题。我有一个深度视图模型图,其中顶级可观察子视图模型数组表示为选项卡,每个选项卡呈现孙子数据的标记。最初我在Knockout构建它之后使用jQuery UI选项卡来标记我的标记。

我有添加,删除和复制这些选项卡式视图模型/域对象的功能。使用jQuery UI选项卡,我最终不得不在其上调用destroy然后重建它,对于像Duplicate这样的情况,我必须先存储所选索引,然后在重新创建后选择该索引+ 1,以选择新创建的选项卡。 / p>

但是现在我已经更加完全接受MVVM作为我的UI的驱动程序并完全剔除了jQuery选项卡,并将我自己的选项卡标题和选项卡内容元素绑定到我的Knockout视图模型上的“isSelected”可观察属性。我发现它更干净,给了我更多的灵活性,标签的标记/ CSS变得简单而优雅。

isSelected属性也意味着我可以通过为每个选项卡指定<div class="child" data-bind="if: isSelected">之类的内容来提高绑定效率。以前(大概)Knockout不必要地处理隐形标签的所有绑定。

这就是我现在通常尝试接近我的UI的方法 - 尽可能避免使用直接的程序UI内容来支持使用绑定。