Scope

The $scope object that gets injected into controllers has some functionality. In addition to this, we will look at the hierarchies and digest cycle of scopes.

Digest cycle

This is an important concept to understand with scopes. The digest cycle, from a high level, is a cycle that checks to see whether any scope variables have been changed. If they have, it then executes a function. Take binding a scope variable to the template with {{variable}}. The digest cycle will now watch this variable and, anytime it changes, it will update the template. If the variable is bound anywhere else, it will be updated as well. This is how Angular "magically" makes values auto update.

A few things to keep in mind is that not everything in the scope is watched. The easiest way to have it watched is to bind it. You can also manually watch values. Also, remember that performance issues can arise when you are watching many variables. The digest cycle goes through all the watchers.

$digest

This is how you can start the digest cycle:

scope.$digest()

Description

This will manually kick off the digest cycle for the scope. In most cases, this does not need to be called. For example, $digest does not need to be called after updating a value from a click event when handled through Angular. Angular will start the digest cycle for you. A good rule of thumb is that if you are changing or updating a value from an Angular event or directive in a controller, you would not need to call $digest.

One case where you may need to call it is when dealing with an asynchronous call in a custom directive.

$watch

This allows you to watch a value or computed value in the digest cycle:

scope.$watch(watch, listener)

Parameters

  • watch(string or function): This is what you want to watch. A string will be evaluated as an expression. The function will have access to the scope through the first parameter. Using a function allows you to watch not only for values, but also calculated values of variables in the scope.
  • listener(function): This function will have the function(newVal, oldVal, scope) signature. This is the function that will execute when the value changes.

Return value

This is a function to deregister the watch.

Description

This is how to manually add a watch to the digest cycle. There are two main reasons to do this. The first is that you will need to run a custom function when a value changes. The other is that you will need to watch a combination or calculation of a value in $scope.

Here is an example that has a watch for a string and a function. The basis of the example is from Controllers, $scope sections. The first watch listens for the hey variable in the scope. The other one watches to see whether the value of hey has three or more characters. It will only fire when this threshold has been crossed and not fire again until it is crossed in the opposite direction:

$scope.$watch('hey', function (newVal, oldVal, scope) {
  alert('Hey was changed from ' + oldVal + ' to ' + newVal);
});

$scope.$watch(function (scope) {
  return scope.hey.length >= 3;
}, function (newVal, oldVal, scope) {
  console.log('Hey listener');
});

$apply

This is a way to manually start the digest cycle:

scope.$apply(func)

Parameters

  • The func(function or string) attribute is a string, it would be evaluated as an expression. If it is a function, the function would be executed.

Return value

This is the return value of the function or expression.

Description

This will manually kick off the digest cycle. Much like $digest, this should not be called for the most part, except for specific situations. The most common situation is when a scope value has been changed outside of Angular, for example, an asynchronous AJAX call that has a reference to a scope value. The update happens outside of the digest loop and Angular does not know as it did not use any Angular methods.

This leads to a best practice to always use Angular's services and functions. If you do so, you should never have to run $apply.

Another best practice is to run your function inside $apply. Angular will catch any errors that are thrown and you can deal with them the Angular way.

Here is an example that updates the scope inside setTimeout after 2 seconds. As the digest loop has finished, it will not see this change unless $apply is called:

setTimeout(function () {
  $scope.$apply(function () { $scope.hey = 'Updated from setTimeout'; });
}, 2000);

Hierarchies

Angular applications only have one root scope but many child scopes. When a variable is referenced, it will check the current scope it is in and then check the parent. This will happen all the way up to the root scope. This is very similar to how JavaScript objects work with the prototype property. You can find more about this in Chapter 8, JavaScript Object-orientated Programming.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.80.45