Angular Non-Extending Accordion

I use angular directive to hide / show content.

The problem I am facing is that the height of the content container does not change.

Here's the plunker: http://plnkr.co/edit/oWXrqoJpaYPDbe4TwT3c?p=preview

If you click the "Show more" button, you will see how the content is hidden, not the height of the change 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); } } }); 

If I check the show-jobs element, I see that it has an initial height of 312px. If I remove this, then it will work as expected.

+7
javascript angularjs css css3 angular-directive
source share
3 answers

As Gilian already said, the problem is that you have a fixed pitch that prevents your section element from automatically getting its height to fit all its contents (including the recently expanded accordion). The solution I can offer for this (which is also very similar to what Bootstrap does, as far as I can tell)

  • Set the section height to auto when the animation is finished, so if the nested divs expand, the section will expand correctly.
  • Re-set the fixed height in section when the user tries to close it before setting its height to 0 so that the closing animation works correctly.

To complete the first part, you can simply define a function that adjusts the height of the section to auto and call it after the extension animation finishes.

 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'; } } 

Since the extension animation takes 0.7 seconds, you can simply call the adjustHeightFunc function with a timeout of 0.8 seconds (I understand that this is not entirely optimal, since if you change the duration of the animation, you will also need to change this timeout, but this best solution i have found so far, any other suggestions are welcome). So at the end of your onClick function, you can:

 $timeout(adjustHeightFunc, 800); 

To make the second part, you should not set the height of the section to 0 when the section should be collapsed, but always set it to the height of its contents. After you do this, and if the section needs to be collapsed, you call a separate function using $ timeout with a value of 0 (so that it runs in a separate digest loop), which sets the height of the section to 0, thereby causing the animation to crash . Thus, your onClick function becomes something like this:

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

See the updated Plunker .

EDIT: As you can see from the comment settings, executing closeAccordionFunc with a timeout of 0 does not work with all browsers. The workaround for this is to declare a CSS class that will set the height of the auto element (using !important to override the height set directly on the element) and use the Angular $animate to add / remove this class to the element and execute closeAccordionFunc after the class is deleted. Thus, the updated onClick function:

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

See also at Plunker .

+6
source share

If your intention is for the slider content directive to slide up and down, hiding / showing content when a button is clicked, it seems to work ... is it normal?

Ok, I understand what is happening. Ok, so the problem is that it has a fixed height of 300 pixels. You can redefine it by height: auto ;, but this will break the container’s slide animation - because the transitions require hard values ​​to start and end the transitions. Now, at least there are two ways to solve this problem:

  • You can remake it to work at maximum height. See max-height animation with CSS transitions
  • You can make the container slip animation at the end of the extension define a class that redefines the height, and when you click the "Show my vacancies →" button, it calculates the new height of the container and assigns it to the inline container. By the way, this problem is a bit complicated. :-)
+6
source share

I think coding only makes sense if you can write less and do more (ok, this is jQuery's motto, but it's good). After this ideea, I have css only the accordion, which I really think can be useful. I have already posted it here . It is based on material here . The basic idea is a radio button utility (it can also be done using checkboxes). I think creating AngularJS code for this is very difficult. The code:

  .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> 

Hope this helps.

EDIT: Due to a pending request by Dave Alperovich to get the appropriate code on the issue of height and dynamic content, I am sending the following code.

 .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> 

This is the editing of the first. I use checkboxes instead of radio buttons and use fixed height. This is proof that this can be done.

If you find this helpful, +1.

+1
source share

All Articles