Alternative to $scope.watch in angular 1.5 x - angularjs

currently I am using watch in angular Js ,but now we have upgraded to angular 1.5x and I don't want to use watch instead I am looking for some thing thing alternative to $scope.watch
I am using a global value defined in the App and I need some alternative to watch which is like a method to be called up when the value of the value is changed any where in the application.

There are basically 2 way of doeing without $watch...
1st) explicitly call the function For exemple if your variable is binded to a n input use ng-change to call the function you need.
2nd) use property setters. For exemple if you want to bind property p of your scope you can use this code in your controller:
var _p = 38;
Object.defineProperty(
$scope,
"p",
{
get : function(){ return _p; },
set : function(val){
_p = val;
callSomeFunction(); // Do what you have been doing with $watch
},
);
But as already said in comments $scope.$watch is not the "evil thing" to avoid

Related

What is the purpose of $watch in angularjs

What is the purpose of $watch in angularjs. Can anyone explain me how it works and what is the purpose of $watch. Thanks in advance
The $scope.watch() function creates a watch of some variable. When you register a watch you pass two functions as parameters to the $watch() function:
A value function
A listener function
Here is an example:
$scope.$watch(function() {},
function() {}
);
The first function is the value function and the second function is the listener function.
The value function should return the value which is being watched. AngularJS can then check the value returned against the value the watch function returned the last time. That way AngularJS can determine if the value has changed. Here is an example:
$scope.$watch(function(scope) { return scope.data.myVar },
function() {}
);
This example valule function returns the $scope variable scope.data.myVar. If the value of this variable changes, a different value will be returned, and AngularJS will call the listener function.
The listener function should do whatever it needs to do if the value has changed. Perhaps you need to change the content of another variable, or set the content of an HTML element or something. Here is an example:
$scope.$watch(function(scope) { return scope.data.myVar },
function(newValue, oldValue) {
document.getElementById("").innerHTML =
"" + newValue + "";
}
);
This example sets the inner HTML of an HTML element to the new value of the variable, embedded in the b element which makes the value bold. Of course you could have done this using the code {{ data.myVar }, but this is just an example of what you can do inside the listener function.
Hope help ful to you.
Take a look at the Angular docs, they are generally pretty good and include examples.
$watch(watchExpression, listener, [objectEquality]);
Registers a listener callback to be executed whenever the
watchExpression changes.
https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch

In angularJs: what's the different between setting $watch on string variable and setting $watch on Object's key?

In angularJs: what's the different between setting $watch on string variable and setting $watch on Object's key?
The detail scenario is as follow:
$scope.activedMenu = {'id' : '...', 'name' : 'menu1'};
$scope.selectedMenuName = 'menu1';
$scope.$watch('activedMenu.name', function () {...});
$scope.$watch('selectedMenuName', function () {...});
So, my question is what's the different between "$scope.$watch('activedMenu.name', function () {...})" with "$scope.$watch('selectedMenuName', function () {...})"? Any help will be appreciated!
(I think these two ways to set a $watch are equivalence, I refer from the scope develop guide! https://docs.angularjs.org/guide/scope)
Basically $watch need string parameter & search for that parameter inside current scope & placed dirty watch on it.
Watching on activedMenu.name OR selectedMenuName is one as the same thing, 1st one will watch on name property of activedMenu, the 2nd one will watch on selectedMenuName scope variable.
The only difference I think is you are watching on single property so you can use object equality option here which deep watches the object change. It could be possible for you 1st watch but watch string should be activedMenu only
$scope.$watch('activedMenu', function(newVal, oldVal){
//on watch code here
}, true);

Accessing ngModel from controller and watch for changes

i have make custom directive which is working good. It's plunker is at http://plnkr.co/edit/GxM78QRwSjTrsX1SCxF7?p=preview
in that directive there is ngModel call deptStation I want access it in controller so that i can use it as parameter in other function to make new array. I also want to watch it also so on every change I can call the function.
<plexus-select items="deptStations" header-text="Select station" text="Select departure..." text-icon="ion-chatbubble-working" text-field="City_Name_EN" text-field2="City_Code" value-field="City_Code" ng-model="deptStation">
</plexus-select>
I tried to write below code but it don't show console log
$scope.$watch('deptStation', function(newValue, oldValue) {
if(oldValue != newValue) {
// perform something
console.log('New Value ' + newValue);
}
I'm not exactly sure about ionic directives, but your issue is probably because one or more of the ionic directives creates a new scope, so just doing ng-model="deptStation" creates a new property in that scope rather than your controller's.
To avoid these issues you should make sure not to bind to primitives, but arrays/objects instead. You should create the property like so (renamed to selectedStation for clarity):
$scope.selectedStation = {value: null};
Then your watch will work:
$scope.$watch('selectedStation.value', function (station) {
console.log('watch', station);
});
http://plnkr.co/edit/96VgPzEXZuzxmHt32Afy?p=preview
As #m59 said though, it seems you'd be better just using two-way binding than ng-model.

AngularJS $watch root scope variable for changes

I have the following $rootScope variable which I use to save the current logged in user privilege level, then I access this variable from other controllers. Is there a way I can watch the rootScope variable for changes in order to update controllers specific variables with any changes to the root scope variable? Below is the code I am using so far, can someone please tell me what I am doing wrong and how to fix it? Thanks
In app.js under .run:
$rootScope.uPLevel = 0;
.controller
$scope.$watch($rootScope.uPLevel, function() {
$scope.userPLevel = $rootScope.uPLevel;
}, true);
The first parameter to $watch should either be a string or a function (docs). Right now you're passing it the value of $rootScope.uPLevel on controller initialization.
$scope.$watch(function() {
return $rootScope.uPLevel;
}, function() {
$scope.userPLevel = $rootScope.uPLevel;
}, true);
Two sidenotes:
It may be prudent to store this value in a service instead of $rootScope.
If uPLevel is only an integer (as your example suggests) then you don't need to pass true as the third parameter - that's only for arrays and objects. If you do want to watch a collection, then I suggest using $watchCollection instead.
I recommend watching $rootScope variables like that:
$scope.$watch('$root.uPLevel', function() {
$scope.userPLevel = $rootScope.uPLevel;
});
This way, When current directive/controller is destroyed. It clears the watch as well. In $rootScope.$watch case, the watch stays forever.

Changed value on AngularJS Service not triggering watch within directive

I'm having an issue getting a watch to work within a directive. I've put together a simple example here. http://plnkr.co/edit/A7zbrsh8gJhdpM30ZH2P
I have a service and two directives. One directive changes a property in the service, and another directive has a watch on that property. I expected the watch to fire when the property is changed but it doesn't.
I've seen a few other questions like this on the site, but the accepted solutions on them have not worked here. I've considered using $broadcast or trying to implement an observer, but it seems like this should work and I don't want to over complicate things if possible.
Mark Rajcok' answer is incomplete. Even with angular.copy(), $watch listener will be called once and never again.
You need to $watch a function:
$scope.$watch(
// This is the important part
function() {
return demoService.currentObject;
},
function(newValue, oldValue) {
console.log('demoService.currentObject has been changed');
// Do whatever you want with demoService.currenctObject
},
true
);
Here the plunker that works: http://plnkr.co/edit/0mav32?p=preview
Open your browser console to see that both the directive and the demoService2 are notified about demoService.currentObject changes.
And btw angular.copy() is not even needed in this example.
Instead of
this.currentObject = newObject;
use
angular.copy(newObject, this.currentObject);
With the original code, the viewer directive is watching the original object, {}. When currentObject is set to newObject, the $watch is still looking for a change to the original object, not newObject.
angular.copy() modifies the original object, so the $watch sees that change.

Resources