javascript - $watchCollection is not triggered - Stack Overflow

i have the following directive:app.directive('rickshawChart', function(){return{$scope: {dat

i have the following directive:

    app.directive('rickshawChart', function()
{
    return{
        $scope: {
            data: '=',
            renderer: '='
        },
        template: '<div></div>',
        restrict: 'E',
        link: function postLink(scope, element, attrs)
        {
           scope.$watchCollection('[data,renderer]', function(newVal, oldVal)
           {
                if(!newVal[0])
                {
                    return;
                }
               var graphEl = element.find("div:first");
               graphEl.html('');
               var graph = new Rickshaw.Graph({
                   element: graphEl[0],
                   width: attrs.width,
                   height: attrs.height,
                   series: [{data: scope.data, color: attrs.color, name: attrs.series}],
                   renderer: scope.renderer
               });
               graph.render();
           });
        }

    }
});

With the following html:

<rickshaw-chart
        data="sightingByDate"
        color="green"
        renderer="renderer"
        width="100%"
        height="100%">
</rickshaw-chart>

Here i fill the data in with the following controller:

    app.controller('CompetenceController', ['$http', '$scope','$sessionStorage','$log','Session','api',  function ($http, $scope, $sessionStorage,$log, Session, api) {

    $scope.result =[ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ];
    $scope.renderer = 'scatterplot';
    $scope.sightingsByDate = _($scope.result)
        .chain()
        .countBy(function(sighting){
            return sighting.y;
        })
        .pairs()
        .map(function(pair){
            return pair;
        })
        .value();
}]);

however from the debugger i am able to see that the $watchCollection is never executed.

What am i doing wrong?

i have the following directive:

    app.directive('rickshawChart', function()
{
    return{
        $scope: {
            data: '=',
            renderer: '='
        },
        template: '<div></div>',
        restrict: 'E',
        link: function postLink(scope, element, attrs)
        {
           scope.$watchCollection('[data,renderer]', function(newVal, oldVal)
           {
                if(!newVal[0])
                {
                    return;
                }
               var graphEl = element.find("div:first");
               graphEl.html('');
               var graph = new Rickshaw.Graph({
                   element: graphEl[0],
                   width: attrs.width,
                   height: attrs.height,
                   series: [{data: scope.data, color: attrs.color, name: attrs.series}],
                   renderer: scope.renderer
               });
               graph.render();
           });
        }

    }
});

With the following html:

<rickshaw-chart
        data="sightingByDate"
        color="green"
        renderer="renderer"
        width="100%"
        height="100%">
</rickshaw-chart>

Here i fill the data in with the following controller:

    app.controller('CompetenceController', ['$http', '$scope','$sessionStorage','$log','Session','api',  function ($http, $scope, $sessionStorage,$log, Session, api) {

    $scope.result =[ { x: 0, y: 40 }, { x: 1, y: 49 }, { x: 2, y: 38 }, { x: 3, y: 30 }, { x: 4, y: 32 } ];
    $scope.renderer = 'scatterplot';
    $scope.sightingsByDate = _($scope.result)
        .chain()
        .countBy(function(sighting){
            return sighting.y;
        })
        .pairs()
        .map(function(pair){
            return pair;
        })
        .value();
}]);

however from the debugger i am able to see that the $watchCollection is never executed.

What am i doing wrong?

Share Improve this question asked Apr 2, 2015 at 9:21 Marc RasmussenMarc Rasmussen 20.6k83 gold badges223 silver badges384 bronze badges 1
  • Ping check my aswer :) – squiroid Commented Apr 2, 2015 at 9:47
Add a ment  | 

3 Answers 3

Reset to default 6

You should use the $watch expression with true as a third parameter:

scope.$watch('[data,renderer]', function (newVal, oldVal) {
         //code
 }, true);

$watchCollection doesn't work for you because you have both an array and a property. In this case is like you're checking contemporarily $scope.$watch('data' and $scope.$watch('renderer'. And if a property in the array changes, the event will not trigger.

There are four types of $watch:

  1. the simpliest is $watch, it simply check if the property or the whole object changed
  2. the second is $watchCollection which watches if any property within an array changed (in your case this doesn't work, because you have both an array and a property)
  3. the third is $watchGroup (since 1.3) which is the most recent version of $watchCollection, which allows you to check an array of expressions (but the same could be achieved with $watchCollection as you were trying to do
  4. $watch('object', function(){...}, true). This check if every single property changed within an object

This is a simplified version of your code, if you press the change value button, you can see how an element in the array is changed and how the event is triggered in the console: http://jsfiddle/27gc71bL/

EDIT: I forgot to add something in my answer. I think there's a typo in your code, you are creating a directive using:

        $scope: {
            data: '=',
            renderer: '='
        },

This is not creating a new scope within the directive. So when you are using scope.data in the link function, you are referring to the $scope.data of the parent (the controller).

What I think you wanted, is to create a new scope in this way:

        scope: {
            data: '=',
            renderer: '='
        },

and, in your controller, bind the array you want to check to sightingByDate.

As doc said

Shallow watches the properties of an object and fires whenever any of the properties change (for arrays, this implies watching the array items; for object maps, this implies watching the properties). If a change is detected, the listener callback is fired.

Watch collection is used for shallow copy of object and array only :) And in your case both things are just value not array or object.

So I guess you need $watchGroup for your work to be done.

$scope.$watchGroup(['teamScore', 'time'], function(newVal, oldVal) {.. }

The code looks correct as long as somewhere either sightingByDate or renderer is getting modified. Perhaps, this is not evident in your code snippet. Make sure any or both of these are getting changed somewhere in your flow to trigger WatchCollection

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744178355a4561862.html

相关推荐

  • javascript - $watchCollection is not triggered - Stack Overflow

    i have the following directive:app.directive('rickshawChart', function(){return{$scope: {dat

    8天前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信