We are no longer accepting contributions to Documentation. Please see our post on meta.

AngularJS

digest loop walkthrough All Versions

0.9.0
0.9.1
0.9.2
0.9.3
0.9.4
0.9.5
0.9.6
0.9.7
0.9.9
0.9.10
0.9.11
0.9.12
0.9.13
0.9.14
0.9.15
0.9.16
0.9.17
0.9.18
0.9.19
0.10.0
0.10.1
0.10.2
0.10.3
0.10.4
0.10.5
0.10.6
1.0.0rc1
g3-v1.0.0rc1
g3-v1.0.0-rc2
v1.0.0rc2
v1.0.0rc3
v1.0.0rc4
v1.0.0rc5
v1.0.0rc6
v1.0.0rc7
v1.0.0rc8
v1.0.0rc9
v1.0.0rc10
v1.0.0rc11
v1.0.0rc12
1.0.0
1.0.1
1.0.2
1.1.0
1.0.3
1.1.1
1.0.4
1.1.2
1.0.5
1.1.3
1.0.6
1.1.4
1.0.7
1.1.5
1.2.0rc1
1.0.8
1.2.0-rc.2
1.2.0-rc.3
1.2.0
1.2.1
1.2.2
1.2.3
1.2.4
1.2.5
1.2.6
1.2.7
1.2.8
1.2.9
1.2.10
1.2.11
1.2.12
1.2.13
1.2.14
1.3.0-beta.1
1.3.0-beta.2
1.3.0-beta.3
1.2.15
1.3.0-beta.4
1.2.16
1.3.0-beta.5
1.3.0-beta.6
1.3.0-beta.7
1.3.0-beta.8
1.3.0-beta.9
1.3.0-beta.10
1.2.17
1.3.0-beta.11
1.2.18
1.3.0-beta.12
1.3.0-beta.13
1.2.19
1.3.0-beta.14
1.2.20
1.3.0-beta.15
1.3.0-beta.16
1.2.21
1.3.0-beta.17
1.2.22
1.3.0-beta.18
1.2.23
1.3.0-beta.19
1.3.0-rc.0
1.2.24
1.3.0-rc.1
1.2.25
1.3.0-rc.2
1.3.0-rc.3
1.3.0-rc.4
1.2.26
1.3.0-rc.5
1.3.0
1.3.1
1.3.2
1.3.3
1.2.27
1.3.4
1.3.5
1.3.6
1.3.7
1.2.28
1.3.8
1.4.0-beta.0
1.3.9
1.3.10
1.4.0-beta.1
1.3.11
1.4.0-beta.2
1.3.12
1.4.0-beta.3
1.3.13
1.4.0-beta.4
1.3.14
1.4.0-beta.5
1.3.15
1.4.0-beta.6
1.4.0-rc.0
1.4.0-rc.1
1.4.0-rc.2
1.4.0
1.3.16
1.4.1
1.3.17
1.4.2
1.4.3
1.4.4
1.3.18
1.4.5
1.3.19
1.4.6
1.5.0-beta.0
1.2.29
1.3.20
1.4.7
1.5.0-beta.1
1.5.0-beta.2
1.4.8
1.5.0-rc.0
1.5.0-rc.1
1.4.9
1.5.0-rc.2
1.5.0
1.4.10
1.5.1
1.5.2
1.5.3
1.5.4
1.5.5
1.4.11
1.5.6
1.4.12
1.5.7
1.2.30
1.5.8
1.2.31
1.4.13
1.2.32
1.6.0-rc.0
1.6.0-rc.1
1.5.9
1.6.0-rc.2
1.6.0
1.5.10
1.6.1
1.5.11
1.6.2
1.6.3
1.6.4
1.6.5

This draft deletes the entire topic.

Examples

  • 4

    Implementing two-way-data-binding, to achieve the result from the previous example, could be done with two core functions:

    • $digest is called after a user interaction (binding DOM=>variable)
    • $watch sets a callback to be called after variable changes (binding variable=>DOM)

    note: this is example is a demonstration, not the actual angular code


    <input id="input"/>
    <span id="span"></span>
    

    The two functions we need:

    var $watches = [];
    function $digest(){
        $watches.forEach(function($w){
            var val = $w.val();
            if($w.prevVal !== val){
                $w.callback(val, $w.prevVal);
                $w.prevVal = val;
            }
        })
    }
    function $watch(val, callback){
        $watches.push({val:val, callback:callback, prevVal: val() })
    }
    

    Now we could now use these functions to hook up a variable to the DOM (angular comes with built-in directives which will do this for you):

    var realVar;    
    //this is usually done by ng-model directive
    input1.addEventListener('keyup',function(e){
        realVar=e.target.value; 
        $digest()
    }, true);
    
    //this is usually done with {{expressions}} or ng-bind directive
    $watch(function(){return realVar},function(val){
        span1.innerHTML = val;
    });
    

    Off-course, the real implementations are more complex, and support parameters such as which element to bind to, and what variable to use

    A running example could be found here: https://jsfiddle.net/azofxd4j/

  • 4

    The previous example is good enough when we need to bind a single html element, to a single variable.

    In reality - we need to bind many elements to many variables:

    <span ng-repeat="number in [1,2,3,4,5]">{{number}}</span>
    

    This ng-repeat binds 5 elements to 5 variables called number, with a different value for each of them!


    The way angular achieves this behavior is using a separate context for each element which needs separate variables. This context is called a scope.

    Each scope contains properties, which are the variables bound to the DOM, and the $digest and $watch functions are implemented as methods of the scope.

    The DOM is a tree, and variables need to be used in different levels of the tree:

    <div>
        <input ng-model="person.name" />
        <span ng-repeat="number in [1,2,3,4,5]">{{number}} {{person.name}}</span>
    </div>
    

    But as we saw, the context(or scope) of variables inside ng-repeat is different to the context above it. To solve this - angular implements scopes as a tree.

    Each scope has an array of children, and calling its $digest method will run all of its children's $digest method.

    This way - after changing the input - $digest is called for the div's scope, which then runs the $digest for its 5 children - which will update its content.


    A simple implementation for a scope, could look like this:

    function $scope(){
        this.$children = [];
        this.$watches = [];
    }
    
    $scope.prototype.$digest = function(){
        this.$watches.forEach(function($w){
            var val = $w.val();
            if($w.prevVal !== val){
                $w.callback(val, $w.prevVal);
              $w.prevVal = val;
            }
        });
        this.$children.forEach(function(c){
            c.$digest();
        });
    }
    
    $scope.prototype.$watch = function(val, callback){
        this.$watches.push({val:val, callback:callback, prevVal: val() })
    }
    

    note: this is example is a demonstration, not the actual angular code

  • 2

    Angular has some magic under its hood. it enables binding DOM to real js variables.

    Angular uses a loop, named the "digest loop", which is called after any change of a variable - calling callbacks which update the DOM.

    For example, the ng-model directive attaches a keyup eventListener to this input:

    <input ng-model="variable" />
    

    Every time the keyup event fires, the digest loop starts.

    At some point, the digest loop iterates over a callback which updates the contents of this span:

    <span>{{variable}}</span>
    

    The basic life-cycle of this example, summarizes (very Schematically) how angular works::

    1. Angular scans html
      • ng-model directive creates a keyup listener on input
      • expression inside span adds a callback to digest cycle
    2. User interacts with input
      • keyup listener starts digest cycle
      • digest cycle calles the callback
      • Callback updates span's contents
Please consider making a request to improve this example.

Syntax

  • $scope.$watch(watchExpression, callback, [deep compare])
  • $scope.$digest()
  • $scope.$apply([exp])

Parameters

Parameters

Remarks

Remarks

Still have a question about digest loop walkthrough? Ask Question

Topic Outline


    We are no longer accepting contributions to Documentation. Drafts cannot be modified.