Animating a button with AngularJS inside ng-repeat

I have this online store that displays items, sizes, prices, etc. and I want to add an animation in .add-to-cart-btn

<button>

so that every time it is clicked the button does some type of animation. I could do it with jQuery something like:

$(document).ready(function() {
  $('.add-to-cart-btn').on('click', function() {
    $(this).addClass('bounce').delay(1000).removeClass('bounce');
  });
});

      

but I am trying to do something "Angular Way" and I think I am close. I have a directive here: thanks to This Post

angular.module('ForeverLeather').directive('animateTrigger', ['$animate', function ($animate) {

  return function (scope, elem, attrs) {
    elem.on('click', function (elem) {
      scope.$apply(function() {
        var el = angular.element(document.getElementsByClassName("add-to-cart-btn"));
        var promise = $animate.addClass(el, "bounce");
        promise.then(function () {
          scope.$apply(function() {
            $animate.removeClass(el, "bounce");
          });
        });
      });
    });
  }
}]);

      

Html

  <div class="col-md-4 col-sm-6" ng-repeat="item in templateItems">

      <div class="product-img-wrapper">
        <img ng-src="{{item.src}}">
      </div>

      <h3 class="product-header">{{item.name}}</h3>
      <p class="lead product-text">
        {{item.description}}
      </p>

      <div class="product-btn-wrapper">
        <select ng-options="size.size as size.text for size in item.sizes" ng-model="item.selectedItem.size"
                class="form-control" ng-change="getPrice(item, item.selectedItem.size)">
          <option value="" disabled>-- Select to view prices --</option>
        </select>
        <span class="text-left product-price">{{item.selectedItem.price | currency}}</span>
        <button ng-click="addToCart(item.type, item.name, item.selectedItem.size);" 
                class="btn btn-lg btn-success add-to-cart-btn animated" animate-trigger>
          <i class="fa fa-cart-plus"></i>&nbsp; Add To Cart
        </button>
      </div>

    </div>

      

This works ... well I guess my problem is var el = angular.element(document.getElementsByClassName("add-to-cart-btn"));

always find the first button on the page with that class name, I need to change that to something like:

var el = angular.element(elem); // invalid
var el = angular.element(this); // invalid

      

so I'm doing the animation on the current click and not on the first page.

+3


source to share


2 answers


But you already have an element, all you need is



return function (scope, elem, attrs) {
    elem.on('click', function () {
      scope.$apply(function() {
        var promise = $animate.addClass(elem, "bounce");
        promise.then(function () {
          scope.$apply(function() {
            $animate.removeClass(elem, "bounce");
          });
        });
      });
    });
  }

      

+4


source


AngularJS animations are meant to be used in a different way.

There are 4 types of animation events

  • enter
  • vacation
  • step
  • add / remove class

If you want to do this "Angular way" with javascript, then what you want to do is capture these events.

In this case, you want to target the button:

(From the docs: https://docs.angularjs.org/api/ngAnimate )



myModule.animation('.slide', [function() {
  return {
    // make note that other events (like addClass/removeClass)
    // have different function input parameters
    enter: function(element, doneFn) {
      jQuery(element).fadeIn(1000, doneFn);

      // remember to call doneFn so that angular
      // knows that the animation has concluded
    },

    move: function(element, doneFn) {
      jQuery(element).fadeIn(1000, doneFn);
    },

    leave: function(element, doneFn) {
      jQuery(element).fadeOut(1000, doneFn);
    }
  }
}]

      

To connect to the event by pressing the, enter

, leave

and move

will not be very useful to you; you want to add or remove the class name in the click event. You could add the class in several ways, but here's one example:

<button ng-class="{'my-animation':model.animationOn}" ng-click="model.animationOn=true">My Button Text</button>

      

However, you will have to remove the class at some point. The most appropriate timing would probably be in the callback for this event using the Angular animation API. Something like that:

myModule.animation('.my-btn', [function() {
  return {
    addClass: function(element, className, doneFn) {
      if(className == 'my-animation') {
        jQuery(element).fadeIn(1000, function() {
          doneFn(); // always call this when you're done
          element.removeClass('my-btn');
        });
      }
    }
  }
}]

      

Also , to let Angular know about you when adding and removing classes in javascript, you must use one of the directives that come with Angular, or use $animate

services in angular. In your first code example, you are adding a class using jQuery, but Angular doesn't know about it.

+2


source







All Articles