Angular 지시문에서 데이터 변경을 감시합니다.


132

$watch내부 데이터를 조작 (예 : 데이터 삽입 또는 제거) 할 때 Angular 지시문에서 변수를 트리거 할 수 있지만 해당 변수에 새 객체를 할당 할 수 없습니까?

현재 JSON 파일에서 간단한 데이터 세트를로드하고 있습니다. 내 Angular 컨트롤러 가이 작업을 수행하고 몇 가지 기능을 정의합니다.

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() {

    };
});

나는이 <button>제대로 호출하는 $scope.add기능을하고, 새로운 개체가 제대로 삽입 $scope.data세트. 설정 한 테이블은 "추가"버튼을 누를 때마다 업데이트됩니다.

<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>

그러나 내가 감시하도록 설정 한 지시문 $scope.data은이 모든 일이 발생해도 해고되지 않습니다.

HTML로 태그를 정의합니다.

<d3-visualization val="data"></d3-visualization>

다음 지시문과 관련이 있습니다 (질문을 위해 다듬어 짐).

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!"시작하는 매우에 메시지를, 그러나 결코 같은 후 나는 "추가"버튼을 누르십시오.

$watch객체에 data객체를 할당 할 완전히 새로운 데이터 세트를 얻지 않고 객체에서 객체를 추가 / 제거 할 때 이벤트를 어떻게 트리거 할 수 data있습니까?


5
newValue가 0, false, ""또는 "데이터가 변경되었습니다!" 발사하지 않습니다. 예를 들어, 원래 값은 true이고 newValue는 false입니다. 거기에 newValue를 사용하는 것으로 충분합니다. 무언가가 변경된 경우에만 시계가 호출됩니다. 객체 인 경우 즉시 호출됩니다.
Mathew Berg

좋은 팁, 감사합니다! 나는 if진술 을 바꾸겠다 .
Evil Closet Monkey

답변:


218

깊은 개체 더티 검사를 활성화해야합니다. 기본적으로 angular는 사용자가보고있는 최상위 변수의 참조 만 확인합니다.

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);
        }
    }
});

범위를 참조하십시오 . $ watch 함수의 세 번째 매개 변수는 true로 설정되어 있는지 더티 더티 검사를 가능하게합니다.

심하게 오염 된 검사는 비용많이 듭니다 . 따라서 전체 data변수 대신 자식 배열을 보아야 할 경우 변수를 직접 봅니다.

scope.$watch('val.children', function(newValue, oldValue) {}, true);

버전 1.2.x는 $ watchCollection을 도입 했습니다

Shallow는 객체의 속성을보고 속성이 변경 될 때마다 발생합니다 (배열의 경우 배열 항목을 보는 것을 의미합니다. 객체 맵의 경우 속성을 보는 것을 의미 함)

scope.$watchCollection('val.children', function(newValue, oldValue) {});

1
잘 작동합니다. 감사합니다!
Evil Closet Monkey

1
기쁘다. 볼 수있는 표현은 매우 다양하므로 $ watch 함수를 계속 실험 해보십시오.
Liviu T.

1
딥 어레이 만 확인하는 방법에 주목 해 주셔서 감사합니다;)
veritas

두 번 이상 공표 할 수없는 것은 유감입니다.
Alex Arvanitidis 2016 년

가장 좋은 답변입니다.
chovy

2

데이터를 깊이있게 트리거하려면 true리스너의 세 번째 인수를 전달해야합니다. 기본적으로 변수는 필드가 아닌 변수가 변경 될false 때만 함수가 트리거됩니다 .


1

jqplot을 사용하여 데이터를 사용할 수있게되면 지시문에 대한 내 버전 :

    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));
                }
            });
        }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.