- Dynamically apply and remove css classes using
ng-class
(see Lesson 1) - Animate elements with CSS transitions or keyframe animations (see Lesson 1)
- Learn how to do animations the Angular way
The following lesson was deconstructed and rebuilt in code from a nice online tutorial video.
bower init
(enter
enter
enter
...)
Take a moment to look at your starter code index.html
:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Angular Animations</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
</head>
<body ng-app="app" ng-controller="AppCtrl">
<h2>Angular Animations</h2>
<button id="myButton" class="btn-primary">Click to fade</button>
<div id="myBadge" class="badge">Fade me</div>
<script type="text/javascript" src="bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="bower_components/gsap/src/uncompressed/TweenMax.js"></script>
<script type="text/javascript" src="bower_components/angular/angular.min.js"></script>
<script type="text/javascript" src="bower_components/angular-animate/angular-animate.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
As you can see, we're using a CDN for Bootstrap CSS (serving the file locally caused problems), an animation library called TweenMax, Angular of course and Angular Animate.
Let's fetch the code before we begin.
bower install angular
bower install bootstrap
bower install gsap --save
(TweenMax seems to have been renamed GreenSock)bower install angular-animate
Add the following to your empty app.js
file as a sanity check:
var app = angular.module('app', ['ngAnimate']);
app.controller('AppCtrl', function(){
console.log('Angular is running');
});
Now we can fire up the server and make sure things work.
http-server
We see the button and the badge. Let's wire up some animation.
We already know how to use jQuery animations. This will work with or without Angular.
$('#myButton').click(function (){
TweenMax.to($('#myBadge'), 1, {opacity: 0});
});
Generally speaking, using jQuery is not the Angular Way.
The .click
method can go. Let's add some Angular code to our controller, instead.
this.fadeIt = function(){
TweenMax.to($('#myBadge'), 1, {opacity: 0});
}
We need to call our new fadeIt
function from the HTML. Where would you add this directive as an attribute?
ng-click="app.fadeIt()"
We also need to do something different with our ng-controller
in order to call fadeIt on app
:
ng-controller="AppCtrl as app"
That should do the trick, but manipulating the DOM inside a controller is a bad idea for several reasons. The code is not reusable and it doesn't leverage the power of directives.
The directive is to be called hideMe
. (That's hide-me
in the markup. Or hide_me
. Or hide:me
.)
hide-me="app.isHidden"
We'll also declare a variable isHidden
, set it to false
by default (thereby duck-typing it a Boolean) and we can toggle its value like so:
this.isHidden = false;
this.fadeIt = function(){
this.isHidden = !this.isHidden;
};
The directive itself will look like this:
app.directive("hideMe", function(){
return function(scope, element, attrs){
scope.$watch(attrs.hideMe, function(newVal){
console.log(newVal);
if(newVal){
TweenMax.to($('#myBadge'), 1, {opacity: 0});
}
});
};
});
You may use scope
or $scope
. At this level they are equivalent.
Angular's $watch
service is like an event listener. By passing in attrs
we can monitor any HTML attributes for changes in the current scope. When a change occurs, $watch
recieves the new value and we can use that data to evoke changes in our app.
Now we have our custom directive but we're still calling it on a specific element in the DOM.
Now you need to pass $animate
into our directive function. We can pass specific functionality to $animate.addClass
and .removeClass
using the animation
service.