【问题标题】:Collapsable panel with bootstrap and knockout带引导和敲除的可折叠面板
【发布时间】:2016-06-06 02:30:10
【问题描述】:

我无法使用 KnockoutJS 制作手风琴,而 Bootstrap 无法正常工作。我是这样定义的:

<div class="panel-group" id="accordion" data-bind="foreach: Advertisers()">
    <div class="panel panel-default">
        <div class="panel-heading">
            <h4 class="panel-title">
                <span data-toggle="collapse" data-bind="html: $data, attr: { 'data-target': '#' + $data }"></span>
            </h4>
        </div>
    </div>
    <div class="panel-collapse collapse" data-parent="#accordion" data-bind="attr: { id: $data }">
        <div class="panel-body">
             ...content...

"Advertisers" 是一个可观察的字符串数组,因此 $data 是一个字符串。我为每个广告商获得一个“行”。

所有行最初都是折叠的,单击一行会展开下面的内容。到目前为止一切顺利。

问题是,当我单击另一行时,我希望先前展开的行会折叠,但事实并非如此。 (我也无法使用 Bootstrap 和 KnockoutJS...)

修改了代码。

【问题讨论】:

  • 我希望我们可以为手风琴做一个更容易处理的自定义绑定...你能检查一下jsfiddle.net/RobertM/qwW7T 的手风琴样本是否适合你吗?
  • 你知道Knockstrap吗?有助于弥合引导和淘汰之间的差距
  • @burktelefon 我在这个标签上做了很多事情,我在这里回答了一个这样的问题检查stackoverflow.com/questions/27396970/…。那应该会有所帮助。 ps:尝试使用$index而不是$data应该是独一无二的欢呼
  • 也可以试试attr: { 'href': '#' + $data }" 而不是attr: { 'data-target': '#' + $data }" 让我们知道
  • 那么我相信它是你需要调查的 css 故障。代码明智的一切都到位。

标签: javascript twitter-bootstrap knockout.js


【解决方案1】:

一个简单的自定义绑定怎么样,它还可以让你的视图稍微整洁一点:

ko.bindingHandlers.bootstrapAccordion = {
  init: function(elem, value, allBindings) {
    var options = ko.utils.unwrapObservable(value()),
        handleClass = '[data-toggle]',
        contentClass = '.collapse',
        openItem = ko.utils.unwrapObservable(options.openItem) || false,
        itemClass = '.' + ko.utils.unwrapObservable(options.item) || '.accordion-group',
        items = $(elem).find(contentClass);

    // toggle: false required to hide items on load
    items.collapse({ parent: elem, toggle: false });
    if (openItem > -1) items.eq(openItem).collapse('show');

    // if the array is dynamic, the collapse should be re-initiated to work properly
    var list = allBindings.get('foreach');
    if (ko.isObservable(list)) {
      list.subscribe(function() { 
        $(elem).find(contentClass).collapse({ parent: elem, toggle: false });              
      });
    }

    $(elem).on('click', handleClass, function() {
        $(elem).find(contentClass).collapse('hide');
        $(this).closest(itemClass).find(contentClass).collapse('show');
    });
  }
};

此绑定需要 2 个参数(容器的类名,以及可选的加载时打开的项目),例如:bootstrapAccordion: {item: 'panel-group', openItem: 0},并且应该在具有 foreach 绑定的同一元素上设置。它假定可折叠部分具有collapse 类,并且切换它们的句柄具有data-toggle 属性。

在这里查看它的实际效果: http://jsfiddle.net/pkvn79h8/22/

【讨论】:

  • itemClass 默认值不正确。请将该行更新为: itemClass = '.' + (ko.utils.unwrapObservable(options.item) || 'accordion-group'),
【解决方案2】:

我扩展了上面的 Tyblitz 示例,包括支持更改图标(例如,+/-、向上/向下箭头)并支持通过将 data-open-next 属性应用于应该移动到下一个面板的任何内容来移动到下一个面板点击。

ko.bindingHandlers.bootstrapAccordion = {
    init: function (elem, value, allBindings) {
        var options = ko.utils.unwrapObservable(value()),
            handleClass = '[data-toggle]',
            contentClass = '.collapse',
            openedClass = ko.utils.unwrapObservable(options.openedClass) || 'fa-minus',
            closedClass = ko.utils.unwrapObservable(options.closedClass) || 'fa-plus',
            openCloseToggleClasses = openedClass + ' ' + closedClass,
            openItem = ko.utils.unwrapObservable(options.openItem) || false,
            itemClass = '.' + (ko.utils.unwrapObservable(options.item) || 'accordion-group'),
            items = $(elem).find(contentClass);

        var initializeItems = function(items) {
            // toggle: false required to hide items on load
            items.collapse({ parent: elem, toggle: false });
            if (openItem > -1) {
                items.eq(openItem).collapse('show');
                items.eq(openItem).closest(itemClass).find('.panel-heading').find('i').toggleClass(openCloseToggleClasses);
                items.eq(openItem).closest(itemClass).find('.panel-heading').addClass('active');
            }
        }

        initializeItems(items);

        // if the array is dynamic, the collapse should be re-initiated to work properly
        var list = allBindings.get('foreach');
        if (ko.isObservable(list)) {
            list.subscribe(function () {
                initializeItems($(elem).find(contentClass));
            });
        }

        $(elem).on('click', handleClass, function () {
            $(elem).find(contentClass).collapse('hide');
            $(this).closest(itemClass).find(contentClass).collapse('show');
            $(this).closest(itemClass).parent().find('.panel-heading i').removeClass(openCloseToggleClasses);
            $(this).closest(itemClass).parent().find('.panel-heading i').addClass(closedClass);
            $(this).closest(itemClass).parent().find('.panel-heading').removeClass('active');
            if ($(this).closest(itemClass).find('.panel-collapse').attr('aria-expanded') === "true") {
                $(this).closest(itemClass).find('.panel-heading i').toggleClass(openCloseToggleClasses);
                $(this).closest(itemClass).find('.panel-heading').addClass('active');
            }
        });

        $(elem).on('click', '[data-open-next]', function () {
            $next = $(this).closest(itemClass).next(itemClass).find(handleClass);
            if ($next.length) {
                $next.click();
            } else {
                $same = $(this).closest(itemClass).find(contentClass);
                $same.collapse('hide');
                $same.parent().find('.panel-heading i').removeClass(openCloseToggleClasses);
                $same.parent().find('.panel-heading i').addClass(closedClass);
                $same.parent().find('.panel-heading').removeClass('active');
            }
        });
    }
};

与此绑定一起使用的示例标记:

<div data-bind="foreach: listOfThings, bootstrapAccordion: { openItem: 0 }">
    <div class="accordion-group">
        <div class="panel panel-default" style="cursor: pointer;" data-toggle>
            <div class="panel-heading">
                <i class="fa fa-plus fa-pull-left fa-2x"></i>
                <h3 data-bind="text: name">Title of expander</h3>
            </div>
        </div>
        <div class="panel-collapse collapse">
            <div class="panel-body">
                <div class="clearfix" data-accordion-content>
                <!-- content goes here -->

                <!-- ko if: $index() < $parent.listOfThings().length -1 -->
                <button data-open-next>Next Thing</button>
                <!-- /ko -->
                </div>
            </div>
        </div>
    </div>
</div>

如果不回馈我会感觉很糟糕:)

【讨论】:

  • 这里有另一个简单的解决方案JSFiddle .. 不确定作者是谁
猜你喜欢
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多