Jak mogę wyzwolić $watch
zmienną w dyrektywie Angular podczas manipulowania danymi wewnątrz (np. Wstawianie lub usuwanie danych), ale nie przypisywać nowego obiektu do tej zmiennej?
Mam prosty zestaw danych, który jest obecnie ładowany z pliku JSON. Mój kontroler Angular robi to, a także definiuje kilka funkcji:
App.controller('AppCtrl', function AppCtrl($scope, JsonService) {
// load the initial data model
if (!$scope.data) {
JsonService.getData(function(data) {
$scope.data = data;
$scope.records = data.children.length;
});
} else {
console.log("I have data already... " + $scope.data);
}
// adds a resource to the 'data' object
$scope.add = function() {
$scope.data.children.push({ "name": "!Insert This!" });
};
// removes the resource from the 'data' object
$scope.remove = function(resource) {
console.log("I'm going to remove this!");
console.log(resource);
};
$scope.highlight = function() {
};
});
Mam taką, <button>
która poprawnie nazywa się $scope.add
funkcją, a nowy obiekt jest poprawnie wstawiony do $scope.data
zestawu. Utworzona przeze mnie tabela aktualizuje się za każdym razem, gdy naciskam przycisk „dodaj”.
<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="child in data.children | filter:search | orderBy:'name'">
<td><input type="checkbox"></td>
<td>{{child.name}}</td>
<td><button class="btn btn-small" ng-click="remove(child)" ng-mouseover="highlight()"><i class="icon-remove-sign"></i> remove</button></td>
</tr>
</tbody>
</table>
Jednak dyrektywa, którą ustawiłem, aby obserwować, $scope.data
nie zostanie zwolniona, gdy to wszystko się stanie.
Definiuję swój tag w HTML:
<d3-visualization val="data"></d3-visualization>
Który jest powiązany z następującą dyrektywą (przycięta ze względu na rozsądek pytania):
App.directive('d3Visualization', function() {
return {
restrict: 'E',
scope: {
val: '='
},
link: function(scope, element, attrs) {
scope.$watch('val', function(newValue, oldValue) {
if (newValue)
console.log("I see a data change!");
});
}
}
});
"I see a data change!"
Wiadomość dostaję na samym początku, ale nigdy po naciśnięciu przycisku „dodaj”.
Jak mogę wyzwolić $watch
zdarzenie, kiedy tylko dodam / usuwam obiekty z data
obiektu, nie otrzymując zupełnie nowego zestawu danych do przypisania do data
obiektu?
źródło
if
oświadczenie.Odpowiedzi:
Musisz włączyć głębokie sprawdzanie zabrudzenia obiektów. Domyślnie kątowe sprawdza tylko odniesienie do obserwowanej zmiennej najwyższego poziomu.
App.directive('d3Visualization', function() { return { restrict: 'E', scope: { val: '=' }, link: function(scope, element, attrs) { scope.$watch('val', function(newValue, oldValue) { if (newValue) console.log("I see a data change!"); }, true); } } });
patrz Zakres . Trzeci parametr funkcji $ watch umożliwia głębokie sprawdzenie, czy jest ustawiony na true.
Zwróć uwagę, że dokładne sprawdzenie jest kosztowne . Więc jeśli chcesz po prostu obserwować tablicę dzieci zamiast całej
data
zmiennej, obserwuj zmienną bezpośrednio.scope.$watch('val.children', function(newValue, oldValue) {}, true);
wersja 1.2.x wprowadziła $ watchCollection
scope.$watchCollection('val.children', function(newValue, oldValue) {});
źródło
Bo jeśli chcesz wywołać swoje dane głęboko w sobie, musisz przekazać trzeci argument
true
swojego listenera. Domyślnie jest tofalse
i oznacza to, że funkcja zostanie wyzwolona tylko wtedy, gdy zmienna zmieni się, a nie pole .źródło
Moja wersja dla dyrektywy, która używa jqplot do wykreślania danych, gdy staną się dostępne:
app.directive('lineChart', function() { $.jqplot.config.enablePlugins = true; return function(scope, element, attrs) { scope.$watch(attrs.lineChart, function(newValue, oldValue) { if (newValue) { // alert(scope.$eval(attrs.lineChart)); var plot = $.jqplot(element[0].id, scope.$eval(attrs.lineChart), scope.$eval(attrs.options)); } }); } });
źródło