# AngularJS - Watch and Apply
## Lesson Objectives
1. Use $watch to listen for changes on variables
1. Use $apply to force a redraw of the page
## Use $watch to listen for changes on variables
### Use 1
We can create event listeners for any property of the $scope variable. This can be useful if you have a scope variable that changes frequently from multiple sources, but you want to perform the same action each time it updates.
```javascript
$scope.$watch('somevar', function(newValue, oldValue){
//will run whenever $scope.somevar changes
});
```
### Example 1
file: index.html
```html
{{somevar}}
```
file: js/app.js
```javascript
const app = angular.module('MyApp', []);
app.controller('MainController', ['$scope', function($scope){
$scope.somevar = 'foo';
$scope.$watch('somevar', function(newValue, oldValue){
//will run whenever $scope.somevar changes
console.log(newValue, oldValue);
});
this.changeScopeVar = function(){
$scope.somevar = 'bar';
};
}]);
```
### Use 2
If no string is passed as first parameter. Entire scope is watched. This is useful for controller properties when controller alias is not known.
**NOTE** that the two parameters for the old value and new value of $scope will appear identical, since they both point to the same object in memory.
```javascript
$scope.$watch(function(newValue, oldValue){
//will run whenever $scope changes
//NOTE: newValue and oldValue will have same property values, since both point the same object, which has been modified
});
```
### Example 2
file: index.html
```html
{{somevar}}
```
file: js/app.js
```javascript
const app = angular.module('MyApp', []);
app.controller('MainController', ['$scope', function($scope){
$scope.somevar = 'foo';
$scope.$watch(function(newValue, oldValue){
//will run whenever $scope.somevar changes
console.log(newValue, oldValue);
});
this.changeScopeVar = function(){
$scope.somevar = 'bar';
};
}]);
```
### Use 3
You can also watch any variables by passing in a function as the first param that returns the variable to be watched
```javascript
$scope.$watch(function(){ return foo; }, function(newValue, oldValue){
//will fire when global foo variable is changed
});
```
### Example 3
file: index.html
```html
```
file: js/app.js
```javascript
const app = angular.module('MyApp', []);
const someThirdPartyVariable = 'foo';
app.controller('MainController', ['$scope', function($scope){
$scope.$watch(
function(){ return someThirdPartyVariable; },
function(newValue, oldValue){
//will fire when global foo variable is changed
console.log(newValue, oldValue);
}
);
this.clickFunction = function(){
someThirdPartyVariable = 'bar';
}
}]);
```
## Use $apply to force a redraw of the page
Angular doesn't watch $scope properties constantly for changes. This would be processing intensive. Instead, it has listeners for events like ng-click, ng-submit, etc. When these fire, Angular looks at the scopes to see if anything changes. If there's a change, Angular will call the $digest cycle, which basically means it will redraw the view.
If you change a $scope property outside of the Angular environment (perhaps through a third party JS library), the view won't refresh. You can manually force the $digest cycle, though. To do this, simply call:
```javascript
$scope.$apply(function(){
//once the code in here completes, force the $digest cycle to run
});
```
### Example
file: index.html
```html
{{foo}}
```
file: js/app.js
```javascript
const app = angular.module('MyApp', []);
app.controller('MainController', ['$scope', function($scope){
$scope.foo = 'foo';
document.querySelector('button').addEventListener('click', function(){
$scope.$apply(function(){
$scope.foo = 'bar';
})
})
}]);
```