AngularJS 1.4+ native implementation for jQuery slideToggle() using $animateCss.
A demo from article: http://blog.assaf.co/native-slide-toggle-for-angularjs-1-4-x/
A Pen by Shlomi Assaf on CodePen.
AngularJS 1.4+ native implementation for jQuery slideToggle() using $animateCss.
A demo from article: http://blog.assaf.co/native-slide-toggle-for-angularjs-1-4-x/
A Pen by Shlomi Assaf on CodePen.
<head> | |
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" /> | |
<script src=" https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-rc.0/angular.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-rc.0/angular-animate.min.js"></script> | |
</head> | |
<body ng-app="app" ng-init="slideToggle1 = true"> | |
<br /> | |
<div class="container-fluid"> | |
<div class=row> | |
<div class="col-sm-4"> | |
<button class="btn btn-primary" | |
ng-click="slideToggle1 =! slideToggle1">Click Me | |
</button> | |
<div class="slide-toggle big-fat-border" | |
ng-show="slideToggle1"> | |
<h1>This is a slide toggle element #1</h1> | |
<p>It should slide</p> | |
</div> | |
</div> | |
<div class="col-sm-4"> | |
<button class="btn btn-success" | |
ng-click="slideToggle2 =! slideToggle2">Click Me | |
</button> | |
<div class="slide-toggle big-fat-border" | |
ng-show="slideToggle2"> | |
<h1>This is a slide toggle element #2</h1> | |
<p>It should slide</p> | |
</div> | |
</div> | |
<div class="col-sm-4"> | |
<button class="btn btn-warning" | |
ng-click="slideToggle3 =! slideToggle3">Click Me | |
</button> | |
<div class="slide-toggle big-fat-border" | |
ng-show="slideToggle3"> | |
<h1>This is a slide toggle element #3</h1> | |
<p>It should slide</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</body> |
(function() { | |
var app = angular.module('app', ['ngAnimate']); | |
app.animation('.slide-toggle', ['$animateCss', function($animateCss) { | |
var lastId = 0; | |
var _cache = {}; | |
function getId(el) { | |
var id = el[0].getAttribute("data-slide-toggle"); | |
if (!id) { | |
id = ++lastId; | |
el[0].setAttribute("data-slide-toggle", id); | |
} | |
return id; | |
} | |
function getState(id) { | |
var state = _cache[id]; | |
if (!state) { | |
state = {}; | |
_cache[id] = state; | |
} | |
return state; | |
} | |
function generateRunner(closing, state, animator, element, doneFn) { | |
return function() { | |
state.animating = true; | |
state.animator = animator; | |
state.doneFn = doneFn; | |
animator.start().finally(function() { | |
if (closing && state.doneFn === doneFn) { | |
element[0].style.height = ''; | |
} | |
state.animating = false; | |
state.animator = undefined; | |
state.doneFn(); | |
}); | |
} | |
} | |
return { | |
addClass: function(element, className, doneFn) { | |
if (className == 'ng-hide') { | |
var state = getState(getId(element)); | |
var height = (state.animating && state.height) ? | |
state.height : element[0].offsetHeight; | |
var animator = $animateCss(element, { | |
from: {height: height + 'px', opacity: 1}, | |
to: {height: '0px', opacity: 0} | |
}); | |
if (animator) { | |
if (state.animating) { | |
state.doneFn = | |
generateRunner(true, | |
state, | |
animator, | |
element, | |
doneFn); | |
return state.animator.end(); | |
} | |
else { | |
state.height = height; | |
return generateRunner(true, | |
state, | |
animator, | |
element, | |
doneFn)(); | |
} | |
} | |
} | |
doneFn(); | |
}, | |
removeClass: function(element, className, doneFn) { | |
if (className == 'ng-hide') { | |
var state = getState(getId(element)); | |
var height = (state.animating && state.height) ? | |
state.height : element[0].offsetHeight; | |
var animator = $animateCss(element, { | |
from: {height: '0px', opacity: 0}, | |
to: {height: height + 'px', opacity: 1} | |
}); | |
if (animator) { | |
if (state.animating) { | |
state.doneFn = generateRunner(false, | |
state, | |
animator, | |
element, | |
doneFn); | |
return state.animator.end(); | |
} | |
else { | |
state.height = height; | |
return generateRunner(false, | |
state, | |
animator, | |
element, | |
doneFn)(); | |
} | |
} | |
} | |
doneFn(); | |
} | |
}; | |
}]); | |
})(); |
.slide-toggle { | |
overflow: hidden; | |
transition: all 2.5s; | |
} | |
.big-fat-border { | |
border: 10px solid blue; | |
} | |
Hello!
First of all, I want to thank you for a nice job. It works fine, but there is a thing which I recommend to change.
When it slides down, height becomes fixed, which causes problems to the container when some contents are added to it.
Could you please help me fix this thing? The main idea is to remove the inline height property from element when animation finishes.
Thanks!!