Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am new to Angularjs. I came across a example online and it got me really confused. Here is the code:

angular.module("testApp",[]).controller("testCtrl", function($scope){

    var data = "Hello";

    $scope.getData = function(){
        return data;
    }

    $scope.setData = function(newData){
        data = newData;
    }
});

Here is the view:

<html ng-app = "testApp">
    <head>
        <script src="lib/Angular.js"></script>
        <script src = "foo.js"></script>
    </head>
    <body ng-controller="testCtrl">
        <div ng-click="setData('Hello Hello')">{{getData()}}</div>
    </body>
</html>

My question is how does angular know when to trigger the getData() method in the view. The click event will change the data. However its a private variable, not attaching to the $scope, which means $scope does not watch the change of it, then how does angular know when to call the getData() in the view? I know it maybe a dumb question, but please help! thank you so much!!

share|improve this question
2  
Any chance you have a link to a Fiddle of this working? –  Justin Niessner Aug 29 '14 at 21:14
1  
It actually is attached to the $scope as well. –  Christopher Marshall Aug 29 '14 at 21:28
    
Ade Attached a Plnkr link below :) –  Ryan.Gao Aug 29 '14 at 21:41

4 Answers 4

up vote 6 down vote accepted

The double-curly expression is what AngularJS calls an observing directive. During the compilation phase, this directive registers listeners on the expression using the $watch method of the scope.

On the other hand, ng-click is what AngularJS calls a listener directive. This type of directive registers a listener with the DOM instead. Whenever the DOM event fires, the directive executes the associated expression inside an $apply call.

This means that after the click expression is executed, a $digest cycle will begin. In this cycle, the scope examines all the registered $watch expressions (e.g. the double-curly expression containing getData()) and calls the listener in case there's a difference from the previous value.

In the end, it is this digest cycle that ensures that all your bound expressions are evaluated.

share|improve this answer
1  
This is an even better explanation. –  Ade Aug 29 '14 at 21:40

The top level controller function runs immediately before it renders the view, in order to initialise the scope. Next the view loads and any logic in the view executes. So when it reaches getData() it returns the output of that function at that time.

The clever part is that Angular automatically binds the data in your views all the way back to the data model, so whenever there is a change in the model (i.e. the source of the data) that automatically updates the value in the view and if necessary will run your getData() method several times.

I saved it here as a Plnkr

share|improve this answer
1  
This is a much better explaination :} –  Christopher Marshall Aug 29 '14 at 21:24
    
Thank you so much! I like @Razvan Mocanu answer too, but I decide to go for easy explanations :) –  Ryan.Gao Aug 29 '14 at 21:42
    
@Razvan's answer is a more technically accurate explanation, although mine is broadly correct in practical terms. –  Ade Aug 29 '14 at 21:48

Your binding {{getData()}} is a "run on evaluation". So when the DOM renders and angular parses it, it sees the () at the end and runs the function. I'll provide citation in a minute when I find it.

share|improve this answer

You don't need the getData in angularjs ... or maybe for other uses than the one you are showing right there.

So the right code would be (without getData) :

    <html ng-app = "testApp">
    <head>
        <script src="lib/Angular.js"></script>
        <script src = "foo.js"></script>
    </head>
    <body ng-controller="testCtrl">
        <div ng-click="setData('Hello Hello')">{{data}}</div>
    </body>
</html>

And with getData :

    $scope.getData = function(){
        data = 'Hello World';
    }

<html ng-app = "testApp">
    <head>
        <script src="lib/Angular.js"></script>
        <script src = "foo.js"></script>
    </head>
    <body ng-controller="testCtrl">
        <div ng-init="getData()" ng-click="setData('Hello Hello')">{{data}}</div>
    </body>
</html>
share|improve this answer
1  
I don't think this answers the question. –  Christopher Marshall Aug 29 '14 at 21:29
    
@ChristopherMarshall : What I wanted to say is that the example is working because it's calling setData which is a $scope function. But if you call an internal function which is not linked to $scope and this function changes the data variable, it won't render. –  HRK Aug 29 '14 at 21:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.