1

I am trying to use jQuery animation with angular's ngAnimate module. In particular, for this example, jQuery's fadeIn and fadeOut. I can get this to work with css transitions, using .ng-enter and .ng-leave etc, but for some reason, not jQuery.

The fade in for the following angular code does not work. The element just shows up straight away.

var app = angular.module('app', ['ngAnimate']);

app.controller('Ctrl', ['$scope',
  function($scope) {
    $scope.data = {};
    $scope.data.toggle = true;
  }
]);

app.animation('.toggle', function() {
  return {
    enter: function(element, done) {
      element.fadeIn(1000, done);
    },
    leave: function(element, done) {
      element.fadeOut(1000, done);
    }
  };
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.0/angular-animate.min.js"></script>

<div ng-app="app" ng-controller="Ctrl">
  <div class="btn btn-primary" ng-click="data.toggle = ! data.toggle">
    Toggle Button
  </div>
  <div class="panel panel-default toggle" ng-if="data.toggle">
    <div class="panel-body">
      Content being toggled
    </div>
  </div>
</div>

However, when using the same fade functions with just jQuery, the animation works fine:

$(function() {
  var container = $('.container');
  var btn = $('.btn');
  var panel = $('.panel');
  var animating = false;

  btn.on('click', function() {
    if (animating)
      return;

    if (panel.is(':visible')) {
      animating = true;
      panel.fadeOut(1000, function() {
        animating = false;
        panel.remove();
      });
      return;
    }

    animating = true;
    panel.appendTo(container).fadeIn(1000, function() {
      animating = false
    });
  });
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div class="container">
  <div class="btn btn-primary">
    Toggle Button
  </div>
  <div class="panel panel-default toggle">
    <div class="panel-body">
      Content being toggled
    </div>
  </div>
</div>

Note, in both cases the panel element is being removed/ added to the DOM. I'm doing this in jQuery to mimic ng-if behaviour.

Is there a way to use jQuery animiations when angular adds an element to the DOM via ng-if? If it's possible with ng-show that would be even better. I don't need workarounds not using jQuery, I can figure those out myself. The answer must use jQuery animations. A small bit of css to support the jQuery animation is fine, however.

12
  • Why are you using jQuery, if you're using Angular? Especially if you can get it to work in Angular already? Commented Apr 21, 2016 at 17:47
  • If I can get it to work using jQuery, then I can use the plethora of jQuery animations and libraries available. Commented Apr 21, 2016 at 17:48
  • 1
    If that's the case, perhaps you can give me an answer that provides effects similar to those such as slideUp slideDown, Blind, Bounce, or indeed any effect from jqueryui.com/effect without having to create the code for those off the shelf effects. Commented Apr 21, 2016 at 17:57
  • 1
    Actually, W3Schools has a good tutorial on the simplicity of transitions: w3schools.com/angular/tryit.asp?filename=try_ng_animation Commented Apr 22, 2016 at 14:54
  • 1
    Example of using jQuery animation in agular docs: docs.angularjs.org/api/ngAnimate#javascript-based-animations Commented Apr 22, 2016 at 18:18

1 Answer 1

2

When you insert an element using angular.js, it uses whatever styles you have set in your CSS and then executes your animation function. Using .fadeIn() on an element that's already visible does nothing. If you want to fade it in, you need to first set its display property to none in either your css:

.toggle{
    display: none;
}

...or in your animation function before fading it in:

element.css("display","none").fadeIn(1000, done);

Here's a working code:

var app = angular.module('app', ['ngAnimate']);

app.controller('Ctrl', ['$scope',
  function($scope) {
    $scope.data = {};
    $scope.data.toggle = true;
  }
]);

app.animation('.toggle', function() {
  return {
    enter: function(element, done) {
      element.css("display","none").fadeIn(1000, done);
    },
    leave: function(element, done) {
      element.fadeOut(1000, done);
    }
  };
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.0/angular-animate.min.js"></script>

<div ng-app="app" ng-controller="Ctrl">
  <div class="btn btn-primary" ng-click="data.toggle = ! data.toggle">
    Toggle Button
  </div>
  <div class="panel panel-default toggle" ng-if="data.toggle">
    <div class="panel-body">
      Content being toggled
    </div>
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

This was the conclusion I came to after a night's sleep, and was about to add it as the answer, but you beat me to it. :) Many thanks. +1 and accepted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.