3

I'm staring my way in AngularJS.

I have created a custom directive:

app.directive('myScroll',function(){
return {
    restrict: 'A',
    transclude: true,

    template: '<div ng-transclude></div>',
    link: function(scope , element , attrs) {

    element.addClass('scroll-pane');

    scope.$watch('tasks', function(newval, oldval){
          if ( newval  ) 
          {

            console.log(newval);
            console.log(newval.length);
        }

    });

        console.log("afer watch exper");
        console.log (tasks);



    }


  };

});

with the following HTML:

<div my-scroll>
        <ul>
            <li data-ng-repeat="task in tasks" class="task-wrapper">
                <div class="task-element">
                    <div class="name">{{task.name}}</div>
                    <div class="text">{{task.action}}</div>
                </div>
            </li>
        </ul>
    </div>

the tasks object is evaluated through a service called by the controller ( if necessary i will post its code).

in the directive code the tasks object is undefined, since i have to get the tasks length to execute more css commands i have to wait for ng-repeat to finish or just wait for tasks variable will be evaluated.

for some reason tasks is always undefined both outside and inside the $watch statement. i can see in the console that "after the watch exper" is printed first and then the "in watch" but still no values. the newval object has [move2:function] but its length property keeps returning 0 but it keeps an array of resources with my tasks.

what am i missing here and how can i execute command when the tasks variable is evaluated?

thanks for the helpers.

0

2 Answers 2

11

You should use scope.tasks to refer the data.

app = angular.module('myApp', []);
app.directive('myScroll', function () {
    return {
        restrict: 'A',
        transclude: true,

        template: '<div ng-transclude></div>',
        link: function (scope, element, attrs) {

            element.addClass('scroll-pane');

            scope.$watch('tasks', function (newval, oldval) {
                if (newval) {
                    console.log(newval);
                    console.log(newval.length);
                }
            });
            console.log("afer watch exper");
            console.log(scope.tasks); //this will log the actual data.
        }
    };
});

function Ctrl($scope) {
    $scope.tasks = [{
        name: "task1",
        action: "action1"
    }]
}
Sign up to request clarification or add additional context in comments.

1 Comment

thanks ! stupid mistake by me... i have one more little question, i can see that the watch expression is called twice, why?? because of the asyc service call to the db?
5

Try passing the 3rd parameter - true to $watch:

scope.$watch('tasks', function(newval, oldval){
    if(newval){
        console.log(newval);
        console.log(newval.length);
    }
},true);

3 Comments

This worked for me, and from the docs I see passing true forces comparison on object equality instead of reference. Do you know why it's needed here?
When you pass true as the 3rd parameter, angular creates a deep copy of the model that's being watched. Also, as the document reads : "To save the value of the object for later comparison, the angular.copy function is used. It also means that watching complex options will have adverse memory and performance implications." So, keeping a watch on huge objects is probably not a good idea.
I got stuck on this a few times so I made a plunker to demonstrate the difference: plnkr.co/edit/DHJPwMOg4LZTSk1uiV9z?p=preview

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.