Writing Robust AngularJS Web Applications
Putting it all together
Let's summarize what we know about AngularJS inner working by examining a
simple example of an input field propagating changes live to DOM:
<input ng-model='name'>
{{name}}
The preceding code will result in two watches registered on a $scope, each one of
them tracking the value of the name model variable. After the initial display, nothing
happens on a page a browser will be sitting in an event loop, and waiting for any
events. It is only when a user starts to type into an field that the whole
machinery is brought to life:
- A new DOM input event is fired. Browser enters the JavaScript
execution context. - A DOM event handler, registered by the input directive is executed. The
handler updates the model value and calls scope.$apply method on a
scope instance. - JavaScript execution context enters the "AngularJS world" and the $digest
loop is started. Upon the first turn of the $digest loop one of the watches
(registered by the {{name}} interpolation directive) is declared as "dirty"
and another turn of the loop is needed. - Since a model change was detected a $watch callback is fired. It updates
the text property of the DOM element where the interpolation expression
is present. - The second turn of the $digest loop is re-evaluating all the watches, but this
time no further changes are detected. AngularJS can declare the model as
"stable" and exit the $digest loop. - JavaScript execution context can process any other, non-AngularJS JavaScript
code. Most of the time there will be none, and a browser will be free to exit
JavaScript execution context. - The UI thread is free to move the rendering context, and a browser can re-
paint the DOM node whose text property has changed. - After rendering is done, a browser can come back to the waiting state in its
event loop.
As you can see, there are a number of steps involved in propagating DOM changes
to the model and back to the DOM.