最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Something like Bootstrap collapsible with angular - Stack Overflow

programmeradmin3浏览0评论

I'm building a small app and I'm using AngularJS. Inside the app I need a collapsible element and using Twitter Bootstrap would be as easy as adding the library and some tags on my target element and the trigger.

But I'm trying not to load other external libraries like bootstrap or any other, so I was trying to achieve the same behavior with Angular :

$scope.collapse = function(target) {

        var that = angular.element(document).find(target),

            transitioned = {
                'WebkitTransition' : 'webkitTransitionEnd',
                'MozTransition'    : 'transitionend',
                'OTransition'      : 'oTransitionEnd otransitionend',
                'msTransition'     : 'MSTransitionEnd',
                'transition'       : 'transitionend'
            },

            _transitioned = transitioned[ Modernizr.prefixed('transition') ],

            height = that.outerHeight(true);

        if (angular.element(that).hasClass("in")) {
            that.height(0);
        } else {
            that.height(height);
        };

        that.on(_transitioned, function() {
            that.toggleClass("in");
        });
    };

As you can see I'm trying to transition the height ( as the element has a transition on the height ) and in the end just add the class in. But that isn't working very well because if I'm listening on the transition end it will trigger on any transition end inside that element.

I would need some help with this, how can I rewrite the bootstrap collapsible just with angular ? I don't need the events that bootstrap has like on shown, hidden or show, hide, I just need to trigger a simple collapse of the element with transition and keep my elements height dynamic ( I don't want a fixed height, otherwise I would just use CSS to achieve the collapse ). I just need to be pinpointed in the right direction :)

I'm building a small app and I'm using AngularJS. Inside the app I need a collapsible element and using Twitter Bootstrap would be as easy as adding the library and some tags on my target element and the trigger.

But I'm trying not to load other external libraries like bootstrap or any other, so I was trying to achieve the same behavior with Angular :

$scope.collapse = function(target) {

        var that = angular.element(document).find(target),

            transitioned = {
                'WebkitTransition' : 'webkitTransitionEnd',
                'MozTransition'    : 'transitionend',
                'OTransition'      : 'oTransitionEnd otransitionend',
                'msTransition'     : 'MSTransitionEnd',
                'transition'       : 'transitionend'
            },

            _transitioned = transitioned[ Modernizr.prefixed('transition') ],

            height = that.outerHeight(true);

        if (angular.element(that).hasClass("in")) {
            that.height(0);
        } else {
            that.height(height);
        };

        that.on(_transitioned, function() {
            that.toggleClass("in");
        });
    };

As you can see I'm trying to transition the height ( as the element has a transition on the height ) and in the end just add the class in. But that isn't working very well because if I'm listening on the transition end it will trigger on any transition end inside that element.

I would need some help with this, how can I rewrite the bootstrap collapsible just with angular ? I don't need the events that bootstrap has like on shown, hidden or show, hide, I just need to trigger a simple collapse of the element with transition and keep my elements height dynamic ( I don't want a fixed height, otherwise I would just use CSS to achieve the collapse ). I just need to be pinpointed in the right direction :)

Share Improve this question edited Nov 20, 2022 at 0:10 Daniel Widdis 9,13113 gold badges48 silver badges68 bronze badges asked Feb 15, 2013 at 15:29 RolandRoland 9,71118 gold badges82 silver badges136 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 7

Seems like you want to just collapse something with CSS3 transitions?

Well, you can do that, but the controller is the wrong place to be doing that. You should do that with directives or in a custom directive. Fortunately, you can do it with the Angular native directives, such as ng-class.

HTML:

<button ng-click="open = !open">Toggle</button>    
<div ng-class="{ showMe: open }" class="collapsable">
  <h3>This should collapse</h3>
</div>

And most importantly, your CSS:

  .collapsable {
    display: inline-block;
    overflow: hidden;
    height: 0;
    transition: height 1s;
    -webkit-transition: height 1s;        
    -moz-transition: height 1s;        
    -o-transition: height 1s;         
  }
  .collapsable.showMe {
    height: 100px;
  }

And here is a plunker of it working.

Important to note, CSS3 transitions will not work in all browsers. Particularly in IE. In the end, I think you'd probably be better off using a plugin that someone else already made, and then leveraging it in a custom directive that watched some boolean value.

I hope that helps.


EDIT

height: auto does not work with CSS Transitions (at least as of the time of this post). So, this is why you'll really want to use someone else's plugin, rather than reinvent the wheel. Even if it's just JQuery's animate() method. The psuedo-code for rolling your own directive would be something like so: (presuming you're using JQuery)

app.directive('collapseWhen', function () {
   return function(scope, elem, attr) {
     scope.$watch(attr.collapseWhen, function(val) {
        var clone = elem.clone().appendTo('body');
        var h = clone.height();
        clone.remove();
        scope.animate({ height: (val ? h : 0) + 'px' }, 1000);
     }
   }
});

and then you'd use it like:

<button ng-click="foo = !foo">Toggle</button>
<div collapse-when="foo">

Again, the above is psuedo-code, I have no idea if it will work or not, it's just to give you an idea to follow if you really want to roll your own.

If i understand the questions, my solution is to use angular $animateCss. Here there are the docs and examples https://docs.angularjs/api/ngAnimate/service/$animateCss

With $animateCss service you can create your own animation using ngAnimate. This is an example of the angular module. The demo is in the link below

var AppModule = angular.module('myApp', ['ngAnimate'])
  .controller('collapseCtrl', ['$scope', function($scope) {
    $scope.btn1 = $scope.btn2 = $scope.btn3 = false;
  }]).animation('.my-collapse', ['$animateCss', function($animateCss) {
    return {
      enter: function(element, doneFn) {
        var height = element[0].offsetHeight;
        return $animateCss(element, {
          from: {
            height: '0px',
            overflow: 'hidden'
          },
          to: {
            height: height + 'px'
          },
          cleanupStyles: true,
          duration: 0.3 // one second
        });
      },
      leave: function(element, doneFn) {
        var height = element[0].offsetHeight;
        return $animateCss(element, {
          to: {
            height: '0px',
            overflow: 'hidden'
          },
          from: {
            height: height + 'px'
          },
          cleanupStyles: true,
          duration: 0.3 // one second
        });
      }
    };
  }]);

https://plnkr.co/edit/DjU1A2vmiBB1dYXjkiN1

Roland, take a look at Bootstrap Project from angular-ui team.

发布评论

评论列表(0)

  1. 暂无评论