knockout.js和jQueryUI创建一个手风琴菜单

Tal*_*ris 11 jquery-ui jquery-ui-accordion knockout.js

尝试让jquery UI和淘汰js共同操作时遇到了一些小问题.基本上我想创建一个手风琴,通过foreach(或模板)从淘汰赛中添加项目.

基本代码如下:

<div id="accordion">
    <div data-bind="foreach: items">
        <h3><a href="#" data-bind="text: text"></a></h3>
        <div><a class="linkField" href="#" data-bind="text: link"></a></div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

这里没有什么令人印象深刻的...问题是,如果我做了类似的事情:

$('#accordion').accordion();
Run Code Online (Sandbox Code Playgroud)

将创建手风琴但内部div将是标题选择器(默认情况下为第一个子节点),因此效果不是所需的效果.

用这个修复东西:

$('#accordion').accordion({ header: 'h3' });
Run Code Online (Sandbox Code Playgroud)

似乎工作得更好,但实际上创造了2个手风琴,而不是一个有2个部分......很奇怪.

我试图探索淘汰模板并使用"afterRender"来重新演奏div,但无济于事......它似乎只重新渲染第一个链接作为手风琴而不是第二个.可能这是因为我的初学者知道了jquery UI.

你知道如何让一切都协同工作吗?

Alf*_*feG 13

我会使用自定义绑定来实现此类功能.

就像RP Niemeyer一样,jQuery Accordion绑定到knockoutjs http://jsfiddle.net/rniemeyer/MfegM/

  • 是的 - 这是一些严肃的手风琴. (3认同)
  • 更新AlfeG jsfiddle使用淘汰模板,并淘汰2.1 http://jsfiddle.net/coffeedannylai/neYHw/9/ (3认同)

Mat*_*man 6

我试图整合淘汰赛和JQuery UI手风琴以及后来的Bootstrap可折叠手风琴.在这两种情况下它都有效,但我发现我必须实现一些变通方法才能正确显示所有内容,尤其是在通过knockout动态添加元素时.提到的小部件并不总是意识到关于淘汰赛的情况,事情可能会搞砸(div高度错误计算等等).特别是对于JQuery手风琴,它倾向于重写html,因为它认为合适,这可能是一个真正的痛苦.

所以,我决定使用核心JQuery和Knockout制作我自己的手风琴小部件.看看这个工作示例:http://jsfiddle.net/matt_friedman/KXgPN/

当然,使用不同的标记和CSS可以根据您的需要进行定制.

好处是它完全是数据驱动的,除了你决定使用的css之外,它不会对布局做出任何假设.你会注意到标记很简单.这只是一个例子.这是为了定制.

标记:

<div data-bind="foreach:groups" id="menu">
    <div class="header" data-bind="text:name, accordion: openState, click: toggle">&nbsp;</div>
    <div class="items" data-bind="foreach:items">
        <div data-bind="text:name">&nbsp;</div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

使用Javascript:

ko.bindingHandlers.accordion = {

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

        var slideUpTime = 300;
        var slideDownTime = 400;

        var openState = ko.utils.unwrapObservable(valueAccessor());
        var focussed = openState.focussed;
        var shouldOpen = openState.shouldOpen;

        /*
         * This following says that if this group is the one that has 
         * been clicked upon (gains focus) find the other groups and 
         * set them to unfocussed and close them.
         */
        if (focussed) {

            var clickedGroup = viewModel;

            $.each(bindingContext.$root.groups(), function (idx, group) {
                if (clickedGroup != group) {
                    group.openState({focussed: false, shouldOpen: false});
                }
            });
        }

        var dropDown = $(element).next();

        if (focussed && shouldOpen) {
            dropDown.slideDown(slideDownTime);
        } else if (focussed && !shouldOpen) {
            dropDown.slideUp(slideUpTime);
        } else if (!focussed && !shouldOpen) {
            dropDown.slideUp(slideUpTime);
        }
    }
};

function ViewModel() {

    var self = this;
    self.groups = ko.observableArray([]);

    function Group(id, name) {

        var self = this;
        self.id = id;
        self.name = name;

        self.openState = ko.observable({focussed: false, shouldOpen: false});

        self.items = ko.observableArray([]);

        self.toggle = function (group, event) {
            var shouldOpen = group.openState().shouldOpen;
            self.openState({focussed: true, shouldOpen: !shouldOpen});
        }
    }

    function Item(id, name) {
        var self = this;
        self.id = id;
        self.name = name;
    }

    var g1 = new Group(1, "Group 1");
    var g2 = new Group(2, "Group 2");
    var g3 = new Group(3, "Group 3");

    g1.items.push(new Item(1, "Item 1"));
    g1.items.push(new Item(2, "Item 2"));

    g2.items.push(new Item(3, "Item 3"));
    g2.items.push(new Item(4, "Item 4"));
    g2.items.push(new Item(5, "Item 5"));

    g3.items.push(new Item(6, "Item 6"));

    self.groups.push(g1);
    self.groups.push(g2);
    self.groups.push(g3);
}

ko.applyBindings(new ViewModel());
Run Code Online (Sandbox Code Playgroud)