Angular 手风琴不展开高度

Angular Accordion not expanding the height

我正在对 hide/show 内容使用 angular 手风琴指令。

我面临的问题是内容容器的高度没有改变。

这是一个笨蛋:http://plnkr.co/edit/oWXrqoJpaYPDbe4TwT3c?p=preview

如果你点击 Show More,你可以看到内容是如何隐藏的,而不是 show-jobs 的高度在变化。

JS:

app.directive('sliderContentDirective', function () {
    return {
        restrict:'A',
        compile: function (element, attr) {
            // wrap tag
            var contents = element.html();
            element.html('<div class="slideable_content" style="margin:0 !important; padding:0 !important" >' + contents + '</div>');

            return function postLink(scope, element, attrs) {
                // default properties
                attrs.duration = (!attrs.duration) ? '0.7s' : attrs.duration;
                attrs.easing = (!attrs.easing) ? 'ease-in-out' : attrs.easing;
                element.css({
                    'overflow': 'hidden',
                    'height': '0px',
                    'transitionProperty': 'height',
                    'transitionDuration': attrs.duration,
                    'transitionTimingFunction': attrs.easing
                });
            };
        }
    };
});

app.directive('sliderToggleDirective', function($document, $timeout) {
    return {
        restrict: 'AE',
        scope: { 
            target: "@"
        },
        link: function(scope, element, attrs) {             

            var timeoutFunc = function () {
                var target = angular.element($document[0].querySelector("#" + scope.target))[0];

                attrs.expanded = false;  
                element.bind('click', function() {

                    var content = target.querySelector('.slideable_content');
                    if(!attrs.expanded) {
                        content.style.border = '1px solid rgba(0,0,0,0)';
                        var y = content.clientHeight;
                        content.style.border = 0;
                        target.style.height = y + 'px';
                    }
                    else {
                        target.style.height = '0px';
                    }

                    attrs.expanded = !attrs.expanded;
                });
            }

            $timeout(timeoutFunc, 0);
        }
    }
});

如果我检查 show-jobs 元素,我可以看到它的初始高度为 312 像素。如果我删除它,那么它会按预期工作。

如果您的意图是让 slider-content-directive 上下滑动,hiding/showing 单击按钮时的内容,它似乎可以正常工作...可以吗?

好的,我明白是怎么回事了。好的,所以问题似乎是固定高度为 300px。您可以将其覆盖为 height: auto;,但这会破坏容器的滑动动画 - 因为过渡需要用于过渡开始和结束的硬值。现在,至少有两种方法可以解决这个问题:

  • 您可以重新处理它以使其适用于最大高度。参见 Animating max-height with CSS transitions
  • 可以做成当容器展开时的滑动动画结束后,设置一个class覆盖高度,点击"Show My Jobs >>"按钮时,计算新的高度容器并将其分配给内联容器。顺便说一下,这个问题有点棘手。 :-)

正如 Giliar 已经说过的,问题在于您有一个固定的高度,这不允许您的 section 元素自动获得其高度以适合其所有内容(包括新扩展的手风琴)。我可以为此提出的解决方案(据我所知,这也是 Bootstrap 所做的)

  1. 在动画结束时将 section 的高度设置为 auto,这样如果嵌套的 div 展开,section 将正确展开。
  2. 当用户尝试关闭它时,重新将固定高度设置为 section,然后再将其高度设置回 0,这样关闭动画将正常工作。

要完成第一部分,您只需定义一个函数,将 section 的高度调整为 auto 并在展开动画完成后调用它。

var adjustHeightFunc = function() {
    var target = angular.element($document[0].querySelector("#" + scope.target))[0];
    if (attrs.expanded) {
        var content = target.querySelector('.slideable_content');
        target.style.height = 'auto';
    }
}

由于展开动画需要 0.7 秒,您只需调用 adjustHeightFunc 函数,超时时间为 0.8 秒(我知道这并不是最佳选择,因为如果您更改动画的持续时间,您还需要更改它超时,但这是我迄今为止找到的最佳解决方案,欢迎提出任何其他建议)。所以在你的 onClick 函数的最后你可以有:

$timeout(adjustHeightFunc, 800);

做第二部分是在折叠部分时不要将 section 的高度设置为 0,而是始终将其设置为其内容的高度。执行此操作后,如果该部分应该折叠,则使用值为 0 的 $timeout 调用一个单独的函数(以便它将在单独的摘要周期中执行),该函数将部分的高度设置为 0,从而触发折叠动画。因此,您的 onClick 函数会变成这样:

element.bind('click', function() {
    var content = target.querySelector('.slideable_content');
    var y = content.clientHeight;
    target.style.height = y + 'px';
    if(!attrs.expanded) {
        content.style.border = '1px solid rgba(0,0,0,0)';
        content.style.border = 0;
    }
    else {
        $timeout(closeAccordionFunc, 0);
    }

    attrs.expanded = !attrs.expanded;
    $timeout(adjustHeightFunc, 800);
});

参见updated Plunker

编辑: 从评论中可以看出,设置 closeAccordionFunc 以超时 0 执行的设置不适用于所有浏览器。一个解决方法是声明一个 CSS class ,它将元素的高度设置为 auto (使用 !important 覆盖直接在元素上设置的高度)并使用 Angular 的 $animate 服务将此 class 添加/删除到元素并在 class 删除后执行 closeAccordionFunc。因此,更新后的 onClick 函数为:

element.bind('click', function() {
    var content = target.querySelector('.slideable_content');
    var y = content.clientHeight;
    target.style.height = y + 'px';
    if(!attrs.expanded) {
        content.style.border = '1px solid rgba(0,0,0,0)';
        content.style.border = 0;
    }
    else {
      $animate.removeClass(angular.element(target), 'auto', function(){$timeout(closeAccordionFunc);});
    }

    attrs.expanded = !attrs.expanded;
    if (attrs.expanded) {
      $timeout(adjustHeightFunc, 800);
    }
});

另见in Plunker

我认为只有少写多做的编码才有意义(好吧,这是jQuery的座右铭,但这是一个很好的座右铭)。按照这个想法,我有一个 css 唯一的手风琴,我真的认为它可能有用。我已经 post 编辑了它 here. It is based on the material here。主要思想是单选按钮的实用性(也可以用复选框制作)。我认为为此制作 AngularJS 代码非常繁重。代码是:

                    .accordion-example .accordion input[type="radio"] {
                        position: absolute;
                        left: -9999rem;
                    }
                    .accordion-example .accordion label {
                        display: block;
                        background: #4f6f8b;
                        color: #fff;
                        text-align: center;
                        padding: 1rem;
                        font-size: .8em;
                        letter-spacing: .13em;
                        padding-left: .13em;
                        padding-right: 0;
                        text-transform: uppercase;
                        cursor: pointer;
                        height: 3.3rem;
                        font-weight: 300;
                        transition: background 400ms, color 400ms, border-radius 400ms;
                    }
                    .accordion-example .accordion label:hover {
                        background: #385670
                    }
                    .accordion-example .accordion .baffle {
                        position: relative;
                        height: 3.3rem;
                        overflow: hidden;
                        transition: height 400ms;
                        -webkit-transform: translateZ(0);
                    }
                    .accordion-example .accordion .baffle-inner {
                        padding: 1.25rem;
                        background: #eee;
                        position: absolute;
                        top: 3.3rem;
                        left: 0;
                        height: 13.5rem;
                        -webkit-overflow-scrolling: touch;
                        overflow: scroll;
                        overflow-y: scroll;
                        overflow-x: hidden
                    }
                    .accordion-example .accordion .baffle-inner :first-child {
                        margin-top: 0
                    }
                    .accordion-example .accordion .baffle-inner :last-child {
                        margin-bottom: 0
                    }
                    .accordion-example .accordion input[type="radio"]:checked + .baffle {
                        height: 16.8rem
                    }
                    .accordion-example .accordion input[type="radio"]:checked + .baffle label {
                        background: #eee;
                        color: inherit;
                        box-shadow: inset 0 -1px rgba(0, 0, 0, .15);
                        font-weight: 300
                    }
                    .accordion-example .accordion input[type="radio"]:checked + .baffle:not(:first-of-type) label {
                        border-radius: 0
                    }
                    .accordion-example .accordion input[type="radio"]:not(:checked) + .baffle + input[type="radio"]:not(:checked) + .baffle label {
                        box-shadow: inset 0 1px rgba(0, 0, 0, .15);
                    }
                    .accordion-example ::-webkit-scrollbar {
                        width: .9375rem
                    }
                    .accordion-example ::-webkit-scrollbar-thumb {
                        background: #849cb1;
                        border: solid #eee;
                        border-width: .375rem .375rem .375rem 0;
                        border-radius: 0 .375rem .375rem 0
                    }
                    .accordion-example ::-webkit-scrollbar-thumb:window-inactive {
                        background: #aaa
                    }
<div class="accordion-example">
                    <div class="accordion">
                        <input type="radio" id="radio-option-1" name="accordion-radios" checked>
                        <div class="baffle">
                            <label for="radio-option-1">Accordion</label>
                            <div class="baffle-inner">
                                Accordions (from 19th century German Akkordion, from Akkord - “musical chord, concord of sounds”) are a family of box-shaped musical instruments of the bellows-driven free-reed aerophone type, colloquially referred to as a squeezebox. A person who plays the accordion is called an accordionist. The concertina and bandoneón are related; the harmonium and American reed organ are in the same family.
                            </div>
                        </div>
                        <input type="radio" id="radio-option-2" name="accordion-radios">
                        <div class="baffle">
                            <label for="radio-option-2">Lorem</label>
                            <div class="baffle-inner">
                                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque tempus bibendum arcu non sodales. Aenean consequat viverra velit sed elementum. Sed id neque eu quam ultricies blandit ut a lacus. Maecenas et feugiat turpis. Suspendisse nec sem massa. Nullam aliquam sem nibh, non pretium ante posuere vitae. Pellentesque rutrum lacinia enim, eget ornare felis egestas vel. Mauris ullamcorper, ex sit amet pellentesque facilisis, tellus nulla sodales mauris, eu euismod ligula leo in diam. Morbi at leo sit amet est suscipit imperdiet at ac nibh. Fusce ex nisi, rutrum sed sollicitudin eget, rutrum id sapien. </p>
                            </div>
                        </div>
                        <input type="radio" id="radio-option-3" name="accordion-radios">
                        <div class="baffle">
                            <label for="radio-option-3">ipsum</label>
                            <div class="baffle-inner">
                                Suspendisse sit amet lorem tempor, feugiat mauris quis, vehicula ante. Maecenas quis mauris quis tortor hendrerit bibendum et sed orci. Donec semper vel risus in scelerisque. Duis consectetur molestie dolor, eu aliquet ipsum maximus et. Ut massa sem, facilisis convallis nisi vel, posuere ullamcorper dolor. Donec accumsan ligula ornare ante convallis ornare. Donec lectus nibh, pharetra eget accumsan ac, vehicula quis elit. Nulla at mi ac metus ornare vehicula. Suspendisse ac metus maximus, semper est sed, gravida nisl. Nunc finibus lectus non magna congue malesuada. Cras auctor volutpat convallis. Pellentesque.
                            </div>
                        </div>
                    </div>
                </div>

希望对您有所帮助。

编辑:由于 Dave Alperovich 提出了关于高度和动态内容问题的适当代码的无数请求,我 post 以下代码。

.accordion input[type="checkbox"], .accordion input[type="radio"] {
    position:absolute;
    left:-9999em
}

.accordion .baffle {
    position:relative;
    overflow:hidden;
    height:100%
}

.accordion label {
    display:block;
    text-align:center;
    padding:1em;
    cursor:pointer;
    height:100%;
    background:#00bfa5;
    color:#000;
    font-weight:300;
    letter-spacing:.13em;
    text-transform:uppercase
}

.accordion label:hover {
    background:#1de9b6
}

.accordion .baffle-inner {
    padding:0 1.25em;
    height:0;
    opacity:0;
    -webkit-transition:all 500ms ease-in-out;
    -o-transition:all 500ms ease-in-out;
    transition:all 500ms ease-in-out
}

.accordion > .baffle > input[type="checkbox"]:checked ~ .baffle-inner, .accordion > .baffle > input[type="radio"]:checked ~ .baffle-inner{
    padding:1.25em;
    height:100%;
    margin-bottom: 20px;
    opacity:1
}

.accordion > .baffle > input[type="checkbox"]:checked ~ label, .accordion > .baffle > input[type="radio"]:checked ~ label {
    background:#eee;
    box-shadow:inset 0 -1px rgba(0,0,0,.4);
    font-weight:300
}
.accordion > .baffle > input[type="checkbox"]:checked ~ label:hover, .accordion > .baffle > input[type="radio"]:checked ~ label:hover {
    background:#1de9b6
}
<div class="accordion">
    <div class="baffle">
        <input id="checkbox-option-1" type="checkbox" checked="checked" name="accordion-checkboxs">
        <label for="checkbox-option-1">Accordion</label>
        <div class="baffle-inner">
            Accordions (from 19th century German Akkordion, from Akkord - “musical chord, concord of sounds”) are a family of box-shaped musical instruments of the bellows-driven free-reed aerophone type, colloquially referred to as a squeezebox. A person who plays the accordion is called an accordionist. The concertina and bandoneón are related; the harmonium and American reed organ are in the same family. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis dignissim felis in lacinia vulputate. Vestibulum suscipit, lacus id tempus sagittis, ex orci molestie turpis, nec pharetra ligula arcu ac nisi. Donec in nisi arcu. Aenean non nisl purus. Fusce pretium lorem eget dui sollicitudin, eu gravida felis egestas. Vivamus orci tellus, efficitur at interdum vitae, ultricies quis urna. Sed ipsum eros, fermentum ornare ultrices vel, pharetra vitae metus. Sed ex metus, consectetur at tellus eget, porttitor molestie dolor. Duis nec metus non est tincidunt consectetur. Curabitur vel turpis sit amet leo fermentum cursus. Cras ligula erat, lobortis ut purus et, accumsan vestibulum lectus. Fusce sed nisl nisl. Aenean eget dolor lacinia, interdum ante id, fringilla orci. Cras eu porttitor est.

Fusce dignissim lectus quis ligula aliquet pretium. Vestibulum consequat risus orci, ac consectetur dolor finibus quis. Aliquam erat volutpat. Proin nunc quam, suscipit eget elementum eu, rhoncus in tortor. Aenean vitae lacinia lorem, maximus elementum urna. Vivamus vitae posuere libero, a fermentum lorem. Duis placerat laoreet ipsum, et malesuada lacus aliquam vitae.

Proin ut mauris ipsum. Suspendisse potenti. Mauris diam erat, ornare vitae tellus eget, elementum fringilla nunc. Maecenas eleifend enim non arcu blandit ullamcorper. Vivamus blandit dictum nulla, accumsan finibus leo blandit in. Curabitur nec tellus a nulla cursus semper. Sed fermentum velit quis pulvinar pellentesque. 
        </div>
    </div>
    <div class="baffle">
        <input id="checkbox-option-2" type="checkbox" name="accordion-checkboxs">
        <label for="checkbox-option-2">Construction</label>
        <div class="baffle-inner">
            Accordions have many configurations and types. What may be technically possible to do with one accordion could be impossible with another:
            <br>The accordion is a free reed instrument and is in the same family as other instruments such as the sheng and khaen. The sheng and khaen are both much older than the accordion and this type of reed did inspire the kind of free reeds in use in the accordion as we know it today.The accordion’s basic form is believed to have been invented in Berlin in 1822 by Christian Friedrich Ludwig Buschmann, although one instrument has been recently discovered that appears to have been built earlier.
        </div>
    </div>
    <div class="baffle">
        <input id="checkbox-option-3" type="checkbox" name="accordion-checkboxs">
        <label for="checkbox-option-3">History</label>
        <div class="baffle-inner">
            <p>The accordion is a free reed instrument and is in the same family as other instruments such as the sheng and khaen. The sheng and khaen are both much older than the accordion and this type of reed did inspire the kind of free reeds in use in the accordion as we know it today.</p>
            <p>The accordion’s basic form is believed to have been invented in Berlin in 1822 by Christian Friedrich Ludwig Buschmann, although one instrument has been recently discovered that appears to have been built earlier.</p>
        </div>
    </div>
</div>

这是对第一个的编辑。我使用复选框而不是单选按钮,并使用非固定高度。这是可以做到的证明

如果觉得有用,+1。