2016-11-24 8 views
0

ng-repeatループ内にあるカスタム属性内の変更を監視するディレクティブを使用しようとしています。 ng-repeatで使用される配列は5秒ごとに更新されます。アイテムが以前の値から変更されたときにdivをアニメーション化したいと思います。

私は$watchを使用して古い値と新しい値を記録していますが、常に同じです。 $watch関数は、データがロードされるとすぐにng-repeatが再びトリガーになるため、スコープの変更を検出できないことを知っています。

目標は、値が変更された場合、divの背景色をアニメーション化することです。

どうすればこの問題を回避できますか?

指令:

.directive('animateOnChange', function($timeout) { 
return function(scope, element, attr) { 
    scope.$watch(attr.animateOnChange, function(nv,ov) { 
    if (nv!=ov) { 
    if(attr.change > 0){ 
     element.addClass('changed-positive'); 
     $timeout(function() { 
     element.removeClass('changed-positive'); 
     }, 1000); 
    }else if (attr.change < 0){ 
     element.addClass('changed-negative'); 
     $timeout(function() { 
     element.removeClass('changed-negative'); 
     }, 1000); 
    } 
    } 
}); 
}; 
}); 

HTML:

<div class="row" ng-repeat="item in data"> 
    <div class="box" animate-on-change="item.activeprice[0]" change="{{item.change[0]}}"> 
    <h2>{{item.desc[0]}}</h2> 
    <p>Time: {{item.asktime[0]}}</p> 
    </div> 
</div> 

$scope.dataは、httpリクエストを介して更新/呼ばなっています。

提案がありますか?

答えて

0

メインコントローラで$watch機能を使用して、変更を監視し、それに基づいてアニメーションを作成しました。 `$ index 'に基づいてng-repeatループの各行にクラスを与えました。

<div class="box box-{{$index}}" ng-style="item.change[0] < 0 && { 'color' :'#c0392b' } || item.change[0] >= 0 && { 'color' :'#2980b9' } "> 
    <h2>{{item.desc[0]}}</h2> 
    <p>Time: {{item.asktime[0]}}</p> 
</div> 

コントローラー:

$scope.$watch('data', function(newVal, oldVal) { 
    $timeout(function() { 
     if (newVal !== oldVal) { 
     for (var i = 0; i < newVal.length; i++) { 
      for (var c = 0; c < oldVal.length; c++) { 
      if(newVal[i].desc[0] == oldVal[c].desc[0]){ 
       if(newVal[i].activeprice[0] !== oldVal[c].activeprice[0]){ 
       if(newVal[i].change[0] > 0){ 
       $(".box-" + i).addClass('changed-positive'); 
       $timeout(function() { 
        $(".box-" + i).removeClass('changed-positive'); 
       }, 10); 
       } else if(newVal[i].change[0] < 0){ 
       $(".box-" + i).addClass('changed-negative'); 
       $timeout(function() { 
        $(".box-" + i).removeClass('changed-negative'); 
       }, 10); 
       } 
       } 
      } 
      } 
     } 
     } 
    }, 300); 
    }, true); 
1

$ watch関数を親スコープに移動することをお勧めします。

$scope.$watch('data', function(newVal, oldVal) { 
    if (newVal !== oldVal) { 
     // You know something is different. 
     // 1. Find items that are different with loop, forEach, etc. 
     // 2. Create changedPositiveItems and changedNegativeItems arrays 
     //  with ids of changed items 
    } 
}, true); 

divの中にng-repeatがあると、このようなことが起こります。ディレクティブ

$scope.itemChangedPositive = $scope.changedPositive.indexOf(item.id) > -1; 
$scope.itemChangedNegative = $scope.changedPositive.indexOf(item.id) > -1; 

インサイド

<div animate-on-change 
    changed-positive="changedPositiveItems" 
    changed-negative="changedNegativeItems" 
    ng-class={'changed-positive-class': itemChangedPositive, 
       'changed-negative-class': itemChangedNegative }> 
    // content of item here 
</div> 

私はあなたのデータの詳細を欠落している可能性がありますが、私は私が考える方向にあなたを指すことを願っています。外部スコープで比較を行い、何が変更されたかを把握し、子スコープに渡します。そこで、特定のアイテムが変更されたかどうかを確認できます。

また、第2パラメータtrueを持つ$scope.$watchは、大きなデータセットを持っている場合、オブジェクトを深く知ることはコストがかかることに注意してください。 1つの回避策は、データをシリアライズして文字列として比較することです。文字列が異なる場合は、コストのかかる比較操作を実行するだけです。

+0

感謝。 '$ watch'関数を親スコープに移動し、変更されたdivを見つけてアニメートするループをいくつか作成しました。 – TietjeDK

関連する問題