web-dev-qa-db-fra.com

Arrêtez l'animation angulaire de se produire sur ng-show/ng-hide

Dans mon application AngularJS, j'utilise fontawesome pour mes fileuses de chargement:

<i class="fa fa-spin fa-spinner" ng-show="loading"></i>

J'utilise également AngularToaster pour les messages de notification qui dépendent de ngAnimate. Lorsque j'inclus ngAnimate dans mon application AngularJS, cela gâche mes chargeurs en les animant de manière étrange. Je veux empêcher cela, mais je ne peux pas trouver un moyen de désactiver l'animation uniquement sur ces chargeurs (il serait également puant de devoir mettre à jour tous les chargeurs que j'ai dans mon application).

Heres un plunkr montrant mon problème exact.

http://plnkr.co/edit/wVY5iSpUST52noIA2h5a

44
Chris Lees

Je pense que la meilleure façon de faire est d’utiliser le $animateProvider.classNameFilter qui vous permettra de filtrer les éléments à animer ou, dans ce cas, à ne pas animer. Nous ferons quelque chose comme:

 $animateProvider.classNameFilter(/^((?!(fa-spinner)).)*$/);
 //$animateProvider.classNameFilter(/^((?!(fa-spinner|class2|class3)).)*$/);

Démo:

http://plnkr.co/edit/lbqviQ87MQoZWeXplax1?p=preview

Angular docs state:

Définit et/ou retourne l'expression régulière de la classe CSS vérifiée lors de l'exécution d'une animation. Au démarrage, la valeur classNameFilter n'est pas du tout défini et permettra donc à $ animate d'essayer de effectuer une animation sur n'importe quel élément. Lors de la définition de classNameFilter valeur, les animations ne seront exécutées que sur les éléments qui ont réussi correspondre à l'expression du filtre. Cela peut améliorer les performances pour périphériques de faible puissance ainsi que les applications contenant beaucoup de opérations structurelles.

Comme autre réponse par le commentaire avec la directive no-animate, vous pouvez écrire une directive ng-show qui s'exécutera avec une priorité plus élevée et désactiver l'animation. Nous ne ferons cela que si l'élément a la classe fa-spinner

  problemApp.directive('ngShow', function($compile, $animate) {
    return {
      priority: 1000,
      link: function(scope, element, attrs) {

        if (element.hasClass('fa-spinner')) {
          // we could add no-animate and $compile per 
          // http://stackoverflow.com/questions/23879654/angularjs-exclude-certain-elements-from-animations?rq=1
          // or we can just include that no-animate directive's code here
          $animate.enabled(false, element)
          scope.$watch(function() {
            $animate.enabled(false, element)
          })

        }
      }
    }
  });

Démo: http://plnkr.co/edit/BYrhEompZAF5RKxU7ifJ?p=preview

Enfin, et similaire à ce qui précède, nous pouvons utiliser la directive no-animate si nous voulons la rendre un peu plus modulaire. Dans ce cas, je nomme la directive faSpin que vous pourriez faire dans la réponse ci-dessus. C’est essentiellement la même chose que nous préservons la directive de la réponse SO mentionnée dans le commentaire du jeu de codes ci-dessus. Si vous ne vous souciez que des problèmes d'animation fa-spin, le nommer de cette façon fonctionne bien, mais si vous avez d'autres problèmes d'animation ng-show, vous voudriez le nommer ngShow et l'ajouter à la clause if.

  problemApp.directive('noAnimate', ['$animate',
    function($animate) {
      return {
        restrict: 'A',
        link: function(scope, element, attrs) {
          $animate.enabled(false, element)
          scope.$watch(function() {
            $animate.enabled(false, element)
          })
        }
      };
    }
  ])

  problemApp.directive('faSpin', function($compile, $animate) {
    return {
      priority: 1000,
      link: function(scope, element, attrs) {

        if (element.hasClass('fa-spinner')) {
          element.attr('no-animate', true);
          $compile(element)(scope);

        }
      }
    }
  });

Démo: http://plnkr.co/edit/P3R74mUR27QUyxMFcyf4?p=preview

59
lucuma

J'ai eu un problème similaire où mon icône continuait à tourner jusqu'à la fin de l'animation, même après la désactivation de la variable $ scope. Ce qui a fonctionné pour moi a été d’envelopper l’élément <i> fa-icon dans une étendue.

<span ng-if="loading"><i class="fa fa-refresh fa-spin"></i></span>

Essayez le!

38
internet-nico

J'ai trouvé un moyen plus facile.

<i class="fa fa-spinner" ng-show="loading" ng-class="{'fa-spin' : loading}"></i>

Plunker Forked: http://plnkr.co/edit/mCsw5wBL1bsLYB7dCtQF

J'ai rencontré un autre petit problème suite à cela. L'icône apparaîtrait hors de position si elle tournait pendant plus de 2 secondes, mais cela est dû à la classe 'ng-hide-add-active'. ajouté dans mon css:

.fa-spinner.ng-hide-add-active {
    display: none !important;
}

et cela s'en est occupé.

EDIT: La solution de Nico est une version légèrement plus propre de la présente, donc je penserais à utiliser la sienne.

17
James Fiala
angular.module('myCoolAppThatIsAwesomeAndGreat')
  .config(function($animateProvider) {

    // ignore animations for any element with class `ng-animate-disabled`
    $animateProvider.classNameFilter(/^((?!(ng-animate-disabled)).)*$/);

  });

Ensuite, vous pouvez simplement ajouter la classe ng-animate-disabled à l’élément souhaité.

<button><i class="fa fa-spinner ng-animate-disabled" ng-show="somethingTrue"></i></button>

3
ilovett

Mise à jour James Fiala Answer

<i class="fa fa-spinner fa-spin" ng-show="loading"></i>

Vous n'avez pas besoin du ng-class mentionné dans @James Fiala Answer. Mais vous devriez avoir fa-spin parmi les membres de la classe.

Ajouter du style

.fa-spinner.ng-hide-add-active {
   display: none !important;
}
0
Fizer Khan