• No results found

Creating removeClass animations with ngClass

AngularJS provides hooks that can be used to define a custom animation when a directive fires a removeClass event. The following directives will generate removeClass events:

f ngShow: This fires the removeClass event after the ngShow expression evaluates to a non-truthy value, and just before the contents are set to hidden

f ngHide: This fires the removeClass event after the ngHide expression evaluates to a truthy value, and just before the contents are set to hidden

f ngClass: This fires the removeClass event just before the class is removed from the element

f ngForm: This fires the removeClass event to remove validation classes f ngModel: This fires the removeClass event to remove validation classes

f ngMessages: This fires the removeClass event to remove the ng-active class when there are no messages, or to remove the ng-inactive class when one or more messages are visible

Getting ready

Suppose that you want to have a div element slide out of the view when a class is removed. Remember that ng-class does not add or remove any elements from the DOM; it merely adds or removes the classes defined within the directive expression.

The initial setup, before animation is implemented, can be structured as follows:

(style.css)

.container {

background-color: black; width: 200px;

height: 200px; overflow: hidden; } .prompt { position: absolute; margin: 10px; font-family: courier; color: lime; } .cover { position: relative; width: 200px; height: 200px; left: 200px; background-color: black; } .blackout { left: 0; } (index.html) <div ng-app="myApp"> <div ng-controller="Ctrl"> <button ng-click="displayToggle=!displayToggle"> Toggle Visibility </button> <div class="container">

<span class="prompt">Wake up, Neo...</span> <div class="cover" ng-class="{blackout: displayToggle}"> </div> </div> </div> </div> (app.js) angular.module('myApp', ['ngAnimate']) .controller('Ctrl', function($scope) { $scope.displayToggle = true; });

How to do it…

When the ng-class value for blackout evaluates to false, it will immediately be stripped out. However, with the inclusion of the ngAnimate module, AngularJS will add in animation hooks, upon which you can define animations for how the class will be removed.

The animation can be defined by a CSS transition, CSS animation, or by JavaScript. The animation definition can be constructed in different ways. CSS transitions and CSS animations will use the removeClass CSS class hooks to define the animation, whereas JavaScript animations will use the ngAnimate directive's removeClass() method.

CSS transitions

Animating a slide-out effect with CSS transitions simply requires a transition that defines the left positioning distance. Remember that ng-class is merely toggling the presence of the blackout class through the use of the addClass and removeClass animation events. This can be done as follows:

(style.css) .blackout-remove { left: 0; } .blackout-remove { transition: all 3s; } .blackout-remove-active { left: 200px; } JSFiddle: http://jsfiddle.net/msfrisbie/L6u4nzv7/ CSS animation

Animating with a CSS animation is just as simple as CSS transitions, as follows:

(style.css) .blackout-remove { animation: 1s slide-out; } @keyframes slide-out { 0% { left: 0;

} 100% { left: 200px; } } JSFiddle: http://jsfiddle.net/msfrisbie/oq5ha3zq/ JavaScript animation

Animating with JavaScript requires that you manually add and remove the relevant CSS classes, as well as explicitly call the animations. Since AngularJS and jqLite objects don't have an animation method, you will need to use the jQuery object's animate() method. This can be done as follows:

(app.js) angular.module('myApp', ['ngAnimate']) .controller('Ctrl', function($scope) { $scope.displayToggle = true; }) .animation('.blackout', function() { return {

removeClass: function(element, className, done){ if (className==='blackout') { $(element) .removeClass('blackout') .css('left', 0) .animate( {'left': '200px'}, 3000, function() { $(element).css('left',''); done(); } ); } else { done(); } } }; });

JSFiddle: http://jsfiddle.net/msfrisbie/4dnokg2o/

How it works…

The ngAnimate directive provides animation hooks for the class that is being removed in order to define animations independent of the actual class. In the context of this ng-class directive implementation, the blackout CSS class is defined explicitly, and the animation hooks build on top of this class name. The following set of tables defines how the removeClass animation state machine operates.

The animation components are defined as follows:

element <div class="cover blackout"

ng-class="{blackout: displayToggle}"> </div>

className 'blackout'

The following table represents a full removeClass animation transition:

Event DOM

The $animate.

removeClass(element, 'blackout') method is called

<div class="cover blackout" ng-class="{blackout: displayToggle}">

</div>

The $animate service runs the JavaScript-defined animations detected in the element; ng-animate is added

<div class="cover blackout ng- animate"

ng-class="{blackout: displayToggle}">

</div>

The .blackout-remove class is added to the element

<div class="cover blackout ng- animate blackout-remove" ng-class="{blackout: displayToggle}">

</div>

The $animate service waits for a single

Event DOM

The .blackout-remove-active

class is added and .blackout is removed (this triggers the CSS transition/ animation)

<div class="cover ng-animate blackout-remove blackout-remove- active"

ng-class="{blackout: displayToggle}">

</div>

The $animate service scans the element styles to get the CSS transition/animation duration and delay

No change in DOM The $animate service waits for the

animation to get completed (via events and timeout)

No change in DOM The animation ends and all the

generated CSS classes are removed from the element

<div class="cover"

ng-class="{blackout: displayToggle}">

</div>

The doneCallback() callback is fired

(if provided) No change in DOM

See also

f The Creating addClass animations with ngShow recipe provides the details of the complementary addClass event