2 votes

Cellule clignotante sur changement de données AngularJS

Je suis nouveau dans Angular et JS et j'ai essayé de faire quelque chose de simple sans succès.

J'ai un tableau avec des données, à chaque fois que ces données sont modifiées, je veux faire une animation de type "fade in fade out" pour qu'elles clignotent. J'ai supposé que je pouvais utiliser $watch pour regarder si un élément change mais ça ne marche pas.

C'est ce que j'ai obtenu jusqu'à présent :

HTML :

<tbody md-body>
   <tr md-row ng-repeat="item in info.data">
      <td md-cell>{{item.name}}</td>
      <td md-cell>{{item.id}}</td>
      <td md-cell>{{item.thing2}}</td>
      <td md-cell>{{item.thing3}}</td>
      <td md-cell>{{item.thing4}}</td>
      <td md-cell>{{item.thing5}}</td>
   </tr>
 </tbody>

JS :

 $scope.info = {
  "data": [
    {
      name: "ELI 0001",
      id: "123",
      thing1: "thing",
      thing2: "thing",
      thing3: "thing",
      thing4: "thing",
      thing5:"thing",
    },
    {
      name: "ELI 0001",
      id: "123",
      thing1: "thing",
      thing2: "thing",
      thing3: "thing",
      thing4: "thing",
      thing5:"thing",
    },
  ]
};

J'ai ajouté cette fonction pour surveiller les changements dans l'ensemble des données, et lorsque c'est le cas, j'ai créé une alerte. J'ai également ajouté la variable initialising pour qu'il ne s'affiche pas dès le chargement.

var initializing = true
$scope.$watch('if',function(){
if (initializing) {
    $timeout(function() { initializing = false; });
  } else {
    alert('hey')
  }

})

Mon problème est le suivant : comment puis-je faire en sorte qu'il observe toutes les cellules et exécute une classe qui ne fait l'animation que sur les données qui ont changé ?

1voto

khateeb Points 109

AS ce fil https://groups.google.com/forum/#!msg/angular/xZptsb-NYc4/rKAxJ3dQhbMJ ce que j'ai fini par faire c'est ça :

app.directive('highlightOnChange', function() {
  return {
    link: function($scope, element, attrs) {
      attrs.$observe('highlightOnChange', function(val) {
        var el = $(element);
        el.removeClass('blink_me ');
        _.defer(function() {
          el.addClass('blink_me ')
        });
      });
    }
  };
});

C'est-à-dire que la création d'une directive respecte la propriété. Vous pouvez alors l'utiliser comme ceci :

<td md-cell highlight-on-change="{{item.name}}"></td>
...

supposez que votre classe css soit :

.blink_me {
  animation: blinker 1s linear infinite;
}    
@keyframes blinker {
  50% {
    opacity: 0;
  }
}

0voto

Tyler Crawford Points 186

Je travaillais sur une approche similaire à celle de @khateeb - sauf que j'utilise un $watch de l'élément ng-model au lieu d'utiliser $observe sur l'attribut de la directive. Les deux fonctionnent !

Plunker : https://embed.plnkr.co/rZVjPmDft997Kmny1LS4/

Snippet :

(function() {

  "use strict";

  var app = angular
    .module('plunker', [])
    .controller('MainCtrl', MainCtrl)
    .directive('flashTd', flashTD);

  function flashTD($timeout, $compile) {
    return {
      scope: {
        ngModel: '='
      },
      link: function($scope, elem, attrs) {

        // Set a watch on ng-model to wait for value change
        $scope.$watch('ngModel', function(newVal, oldVal) {
          if (newVal !== oldVal) {
            // Flash row
            // var row = angular.element(elem[0].parentNode.parentNode);

            // Flash td
            var td = angular.element(elem[0].parentNode);

            // Using a timeout to simulate remote data change
            $timeout(function() {

              if (td.hasClass('flash')) {
                td.removeClass('flash');
              }

              $timeout(function() {
                td.addClass('flash')
              })

            }, 2000)

          }
        })
      }
    }
  }

  MainCtrl.$inject = ["$scope"];

  function MainCtrl($scope) {

    // Sample Data
    $scope.info = {
      "data": [{
        name: "ELI 0001",
        id: "123",
        thing1: "thing",
        thing2: "thing",
        thing3: "thing",
        thing4: "thing",
        thing5: "thing",
      }, {
        name: "ELI 0001",
        id: "1234",
        thing1: "thing",
        thing2: "thing",
        thing3: "thing",
        thing4: "thing",
        thing5: "thing",
      }]
    };

  }

})()

.editPencil:hover {
  cursor: pointer;
}

/* https://stackoverflow.com/questions/14607695/flashing-table-row */

@keyframes flash {
  from {
    background-color: #ffbe76;
  }
  to {
    background-color: inherit;
  }
}

.flash {
  animation: flash 1s 1;
}

<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS - Flash TD on Change</title>
  <link data-require="bootstrap@3.3.7" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
  <link rel="stylesheet" href="style.css" />

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script data-require="bootstrap@3.3.7" data-semver="3.3.7" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>

  <script data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.20/angular.js" data-semver="1.3.20"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <div class="container">
    <div class="row">
      <div class="col-xs-12">
        <div class="jumbotron text-center">
          <h3>AngularJS - Flash TD on Change</h3>
        </div>
      </div>
      <div class="col-xs-12 col-sm-12 col-md-12">
        <form class="form">
          <div class="form-group">
            <table class="table">
              <thead>
                <tr>
                  <th></th>
                  <th>Name</th>
                  <th>Id</th>
                  <th>Thing1</th>
                  <th>Thing2</th>
                  <th>Thing3</th>
                  <th>Thing4</th>
                  <th>Thing5</th>
                </tr>
              </thead>
              <tbody>
                <tr ng-repeat="item in info.data">
                  <td class="editPencil glyphicon-pencil text-center" style="transform: rotate(45deg)" ng-click="editRow = !editRow"></td>
                  <td>
                    <span ng-hide="editRow">{{ item.name }}</span>
                    <input type="text" class="input-sm" ng-model="item.name" ng-hide="!editRow" flash-td />
                  </td>
                  <td>
                    <span ng-hide="editRow">{{ item.id }}</span>
                    <input type="text" class="input-sm" ng-model="item.id" ng-hide="!editRow" flash-td />
                  </td>
                  <td>
                    <span ng-hide="editRow">{{ item.thing1 }}</span>
                    <input type="text" class="input-sm" ng-model="item.thing1" ng-hide="!editRow" flash-td />
                  </td>
                  <td>
                    <span ng-hide="editRow">{{ item.thing2 }}</span>
                    <input type="text" class="input-sm" ng-model="item.thing2" ng-hide="!editRow" flash-td />
                  </td>
                  <td>
                    <span ng-hide="editRow">{{ item.thing3 }}</span>
                    <input type="text" class="input-sm" ng-model="item.thing3" ng-hide="!editRow" flash-td />
                  </td>
                  <td>
                    <span ng-hide="editRow">{{ item.thing4 }}</span>
                    <input type="text" class="input-sm" ng-model="item.thing4" ng-hide="!editRow" flash-td />
                  </td>
                  <td>
                    <span ng-hide="editRow">{{ item.thing5 }}</span>
                    <input type="text" class="input-sm" ng-model="item.thing5" ng-hide="!editRow" flash-td />
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </form>
      </div>
    </div>
  </div>

</body>

</html>

Directive

Dans ma démo, je clignote l'option td mais vous pouvez tout aussi bien le changer pour faire clignoter la ligne de table de la cible en utilisant l'option commentée row au lieu de la variable td variable.

app.directive('flashTd', flashTD);

function flashTD($timeout, $compile) {
    return {
      scope: {
        ngModel: '='
      },
      link: function($scope, elem, attrs) {

        // Set a watch on ng-model to wait for value change
        $scope.$watch('ngModel', function(newVal, oldVal) {
          if (newVal !== oldVal) {
            // Flash row
            // var row = angular.element(elem[0].parentNode.parentNode);

            // Flash td
            var td = angular.element(elem[0].parentNode);

            // Using a timeout to simulate remote data change
            $timeout(function() {

              if(td.hasClass('flash')) {
                td.removeClass('flash');
              }

              $timeout(function() {
                td.addClass('flash')
              })

            }, 2000)

           }
        })
      }
    }
  }

Élément HTML

 <input type="text" class="input-sm" ng-model="item.thing2" ng-hide="!editRow" flash-td />

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X