Reputation: 65
I am new to AngularJS and at the moment I'm trying out AngularJS animations.
I wrote a CSS animation class that I would like to apply to a Twitter Bootstrap badge on the "Message" button when the value on the badge changes.
The unread message count is handled by the "MessagesCtrl" controller.
For now, the count changes on a button click ("Add Message").
Here is the complete application that I have so far:
<!DOCTYPE html>
<html ng-app="ExampleApp">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular-animate.min.js></script>
<style rel="stylesheet">
@-webkit-keyframes shake {
0% { -webkit-transform: translate(2px, 2px) rotate(20deg); }
20% { -webkit-transform: translate(-4px, -4px) rotate(-20deg); }
40% { -webkit-transform: translate(2px, 2px) rotate(20deg); }
60% { -webkit-transform: translate(-2px, 2px) rotate(-20deg); }
80% { -webkit-transform: translate(4px, -4px) rotate(20deg); }
100% { -webkit-transform: translate(-2px, 2px) rotate(-20deg); }
}
.shake {
-webkit-animation-name: shake;
-webkit-animation-duration: 0.6s;
-webkit-transform-origin: 50% 50%;
-webkit-animation-iteration-count: 1;
-webkit-animation-timing-function: linear;
}
</style>
<script>
var app = angular.module("ExampleApp", ['ngAnimate']);
app.controller("MessagesCtrl", ['$scope', function ($scope) {
$scope.count = 0;
$scope.addMessage = function () {
$scope.count++;
};
}]);
app.directive('shake', ['$animate', 'MessagesCtrl', function ($animate) {
return {
scope: {
count: '='
},
link: function(scope, element, attrs) {
scope.$watch(attrs, function() {
$animate.addClass(element, 'shake').then(function() {
element.removeClass('shake');
});
});
}
};
}]);
</script>
</head>
<body ng-controller="MessagesCtrl">
<button class="btn btn-primary" type="button">
Messages <span shake id="badgeMessage" class="badge" ng-if="count > 0">{{ count }}</span>
</button>
<button ng-click="addMessage()">Add Message</button>
</body>
</html>
When you click the "Add Message" button, the unread count changes, but the shake animation isn't applied on the badge. Can anyone see why this isn't happening? I think the problem is that I'm not including the $scope of the controller into the directive, but I'm not sure how to do this.
The animation is called inside the "shake" attribute directive.
Thank you for your time and assistance.
Upvotes: 1
Views: 3813
Reputation: 38490
Pass count
to the isolated scope you have set up:
<span shake id="badgeMessage" class="badge" count="count" ...
Also change your ng-if
to ng-show
.
Then watch the count:
scope.$watch('count', function(newValue, oldValue) {
if (newValue === oldValue) return;
$animate.addClass(element, 'shake').then(function() {
element.removeClass('shake');
});
});
Demo: http://plnkr.co/edit/pf5S0e705LK1q1OTGTcq?p=preview
If you want to continue to use ng-if
instead you can do this to get it to animate the first time:
scope.$watch('count', function(newValue, oldValue) {
if (newValue === oldValue) return;
animate();
});
var animate = function() {
$animate.addClass(element, 'shake').then(function() {
element.removeClass('shake');
});
};
$timeout(animate);
Demo: http://plnkr.co/edit/sgSTOB5yqiaSgJL5Adl6?p=preview
Upvotes: 4