Angular js - 值更改时突出显示dom

时间:2013-11-21 08:31:12

标签: javascript angularjs angularjs-directive

Angular noobie在这里。 我想知道当范围中的值通过某种方式改变时,更改dom的最佳方法是什么。我读到将dom操作逻辑放在控制器中并且这是指令的工作并不好。

这是一个plunkr

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

基本上,当通过单击上面的plunkr中的加载数据按钮更改数据时,我希望其值更改的单元格自动突出显示。我不能让它为我的生活工作。

任何帮助?

3 个答案:

答案 0 :(得分:27)

我认为观察每个荧光笔的具体值而不是观看整个集合会更好。例如:

<td highlighter="person.firstName">{{ person.firstName }}</td>

这样,highlighter - 指令可以非常简单,例如:

app.directive('highlighter', ['$timeout', function($timeout) {
  return {
    restrict: 'A',
    scope: {
      model: '=highlighter'
    },
    link: function(scope, element) {
      scope.$watch('model', function (nv, ov) {
        if (nv !== ov) {
          // apply class
          element.addClass('highlight');

          // auto remove after some delay
          $timeout(function () {
            element.removeClass('highlight');
          }, 1000);
        }
      });
    }
  };
}]);

尽管如此,为了实现这一目标,您必须告诉角度数据实际发生了变化。目前,对象标识的角度轨迹people不是这种情况。在您覆盖它的那一刻,angular将删除所有相关的dom元素。为了适应这种情况,请使用:

ng-repeat="person in people track by $index"

将告诉angular将数组的索引视为标识。

演示:http://jsbin.com/vutevifadi/1/

答案 1 :(得分:6)

感谢您发布上述答案。我注意到,如果值经常变化,动画会闪烁,当另一个动画已经激活时,会触发超时。

如果已设置超时,我已通过重置超时来解决此问题。

另外,我添加了代码来检查值是增加还是减少,并设置不同的css类。

app.directive('newvalue', ['$timeout', function($timeout) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        element.addClass('newvalue');
        scope.$watch(attrs.newvalue, function (nv, ov) {
        function settimeout() {
            attrs.timeout = $timeout(function () {
                element.removeClass('newvalue-up');
                element.removeClass('newvalue-down');
                attrs.timeout = null;
            }, 1000);
        }
        if (nv !== ov) {
            if(attrs.timeout) {
                //newvalue already set.. reset timeout
                $timeout.cancel(attrs.timeout);
                settimeout();
            } else {
                if(nv > ov) {
                    element.addClass('newvalue-up');
                } else {
                    element.addClass('newvalue-down');
                }
                settimeout();
            }
        }
      });
    }
  };
}]);

答案 2 :(得分:3)

经过一番阅读后,我注意到考虑到性能,使用$watch存在一些疑问。我找到了使用$observe的其他解决方案。

好好阅读$watch$observehttps://stackoverflow.com/a/14907826/2901207

的javascript:

   
var app = angular.module('angularjs-starter', []);
app.directive('highlightOnChange', function() {
  return {
    link : function(scope, element, attrs) {
      attrs.$observe( 'highlightOnChange', function ( val ) {
        console.log("Highlighting", val);
        element.effect('highlight');
      });
    }
  };
});

app.controller('myController', function($scope, $timeout) {
  $scope.val = 1;
  $scope.updateVal = function() {
    $scope.val = $scope.val + 1;
  };
}); 

HTML:                                                             

  <body ng-controller="myController">
    <div highlight-on-change="{{val}}">
      Total: {{ val }}
    </div>
    <button ng-click="updateVal()">Add to Total</button>
  </body>

原始来源:http://plnkr.co/edit/FFBhPIRuT0NA2DZhtoAD?p=preview 来自这篇文章:https://groups.google.com/d/msg/angular/xZptsb-NYc4/YH35m39Eo2wJ

更复杂的用法,对我来说非常合适,因为它会在更新到来时突出显示特定列。

<table class="table table-hover">
        <tr>
            <th ng-repeat="col in fc.tableColumns"><!--fc is a controller-->
                {{col.displayName}}
            </th>
        </tr>
        <tr ng-repeat="item in fc.items track by item.id">
            <td highlight-on-change="{{value}}" ng-repeat="(key,value) in item">
               @*{{key}} =*@ {{value}}
            </td>
        </tr>
    </table>

正如我所说,更新特定列,同时在控制器中的某处执行此操作。

   
items[index] = item;//item from server