Angular js - Выделите dom при изменении значения
Angular noobie здесь.
Я хотел бы знать, что является лучшим способом изменить dom, когда значение в области изменяется каким-то образом. Я читал, что нехорошо поставить логику манипуляции dom в контроллер, и это задача директив.
Вот plunkr
http://plnkr.co/edit/xWk5UBwifbCF2raVvw81?p=preview
В основном, когда данные изменяются, нажав кнопку загрузки данных в plunkr выше, я хочу, чтобы ячейки, значения которых были изменены, автоматически выделялись. Я не могу заставить его работать для меня.
Любая помощь?
Ответы
Ответ 1
Я думаю, было бы лучше наблюдать конкретное значение за ярлык вместо просмотра всей коллекции. Например:
<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);
}
});
}
};
}]);
Хотя для этого вам нужно будет сообщить angular, что данные действительно изменились. В настоящее время это не так, как angular отслеживает people
по идентификатору объекта. В тот момент, когда вы перезапишите его, angular удалит все связанные элементы dom. Для этого используйте:
ng-repeat="person in people track by $index"
который сообщит angular обработать индекс массива как идентификатор.
demo: http://jsbin.com/vutevifadi/1/
Ответ 2
Спасибо за отправку ответа выше. Я заметил, что анимация будет мерцать, если значение изменяется часто, и тайм-аут будет запущен, пока еще активна другая анимация.
Я исправил это, сбросив таймаут, если тайм-аут уже установлен.
Кроме того, я добавил код, чтобы проверить, увеличивается или уменьшается значение, и задает другой класс 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();
}
}
});
}
};
}]);
Ответ 3
После некоторого чтения я заметил, что есть некоторые сомнения в использовании $watch
, учитывая производительность. Я нашел другое решение, используя $observe
.
Хорошо читать на $watch
и $observe
: fooobar.com/info/18387/...
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