AngularJS allows you to implement two-way data binding. However, the interesting part is how it detects model changes? The model is usually a plain object like the code below. We can change the name property of $scope.user
but how does AngularJS detect the model changed? Does AngularJS enum all the properties of the $scope
object?
angular.module('myApp', [])
.controller('BusinessCardController', function($scope){
$scope.user = {
name: 'Tanay Pant'
}
});
<input type="text" ng-model="user.name" placeholder="Full Name" />
AngularJS creates a two way data-binding between the select element and the $ctrl. orderProp model. $ctrl. orderProp is then used as the input for the orderBy filter.
For two-way data binding, declare a private property and access its value using get and set methods in the component class. Then, assign that property to [(ngModel)] . For example, declare a private property with a get and set method, as shown below. Now, assign userName to [(ngModel)] in the template.
AngularJS follows Two-Way data binding model.
In one-way binding, the flow is one-directional. In a two-way binding, the flow is two-directional. This means that the flow of code is from ts file to Html file. This means that the flow of code is from ts file to Html file as well as from Html file to ts file.
There is a digest cycle, where the scope examines all of the $watch expressions and compares them with the previous value. It looks at the object models for changes, if the old value isn't the same as the new value, AngularJS will update the appropriate places, a.k.a dirty checking.
In order for the digest cycle to be execute $apply(fn)
has to be run, this is how you enter the Angular world from JavaScript. How does $apply(fn)
get called (taken from AngularJs integration with browser):
Data Binding
Digest Cycle Explanation
In order to achieve two-way binding, directives register watchers. For a page to be fast and efficient we need to try and reduce all these watchers that we create. So you should be careful when using two-way binding - i.e. only use it when you really needed. Otherwise use one-way:
<h1> {{ ::vm.title }} </h1>
Here it is quite obvious that the title of the page probably won't be changed while the user is on the page - or needs to see the new one if it is changed. So we can use ::
to register a one-way binding during the template linking phase.
The main issues I've seen with explosions of watchers are grids with hundreds of rows. If these rows have quite a few columns and in each cell there is two-way data binding, then you're in for a treat. You can sit back and wait like in modem times for the page to load!
Two-way binding is limited almost exclusively to elements that use ng-model
. The direction going from view to model uses standard event handlers to detect changes that must be updated within the model (e.g., onchange
). The direction going from the model back to the view is updated during a $digest
. But we do not call $digest
directly.
Every element that is on your page that is going to respond to the digest cycle will, somewhere, attach a listener and an expression to its scope using $watch
. When you write {{ foo() }}
, or when you use ng-model='user.name'
, internally there is a call to $watch
made on your behalf with a Javascript expression that will be run every time a digest cycle is run. This registration might happen during the compile of the template (our first example), or it might happen during the link phase of a directive (our second).
There is no magic here. The listeners that are attached are regular functions -- in our example, the listener for the expression foo()
is provided for you, and it will update the html text on the page, while the listener for the expression user.name
will call setText
, or setOption
, or whatever is required by the particular input which ng-model
has been attached.
While angular can handle most of the listening, you can attach your own watch expressions with your own listeners manually inside any function that has access to a scope (scope is important because we will tear down those watchers if the corresponding parts of the page are removed). Be mindful of excess. Bindings aren't free, and the more things that are bound, the slower the page will respond. One-time bindings are one way of reducing this cost. Using $on
with $emit
and $broadcast
are another.
So when is digest called? It is certainly not automatic. If the digest cycle is running, it means someone somewhere called $apply
on their scope or on the root scope. ng-model
attaches handlers which will respond to regular html events and will make calls to $apply
on your behalf. But foo()
, on the other hand, will never get called until some other bit of script somewhere calls $apply
. Fortunately, most functions that you fill out for angular wrap those functions with a call to $apply
, so you don't often have to make the call yourself (e.g., $timeout
is wrapped with $apply
, which is why we use it instead of setTimeout
). But if you were using something outside of the scope of angular (a 3rd party library that connects to events), you would need to remember to call $apply
yourself, and just like above, you can do this manually by calling $apply
anywhere you have access to a scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With