I am using Angular v1.3.13.
I need to watch a global variable in order to enable/disable certain buttons in the template view. I know the global variable is changing based on console.log output but its not updating in the controller...or I am not watching it properly.
While in this controller I need to initiate the $watch and keep watching while the user stays in this view/controller.
$scope.$on('$ionicView.beforeEnter', function () {
var gpsTracker = this;
gpsTracker.gpsEnabled = mapInfo.gpsEnabled;
$scope.$watch(angular.bind(this, function (gpsEnabled) {
return this.gpsEnabled;
}, function () {
getLocationAuth()
}));
});
I have tried several iterations but nothing has worked. The object variable mapInfo.gpsEnabled is what I am try to track.
Related
In my controller I want to be notified when a variable value is changed. My requirement is when value of a variable will change a function will be invoked. So I am using $watch. My code is as follow.
var Canvas = angular.module('canvas');
Canvas.controller("excelOperation",function($scope,Data,SharedData,$http){
$scope.tbody=$scope.$parent.shared.previews;
$scope.$watch('$parent.shared.previews',function(newVal,oldVal){
console.log("WORKING");
})
setInterval(function(){
console.log($scope.$parent.shared.previews);
},1000)
/**
* Populate table function to populate excel table
*/
$scope.populateTable=function()
{
}
})
angular.bootstrap(document.getElementById("page"), ['canvas']);
But issue is $watch is working only when I refresh my page. Though the setInterval is printing the changed value of the variable $watch is not being invoked.
N.B. $scope.$parent.shared.previews is an object
What am I doing wrong?
And what I told to achieve, is this a good way to do?
You are watching a object's property change, deep watch is required. Second, to watch parent scope variable, maybe you'd better write like this $scope.$parent.$watch(...).
var deepWatch = true;
$scope.$watch('$parent.shared.previews', function(newVal, oldVal) {
console.log("WORKING");
}, deepWatch);
How to stop $watch while changing the object
Here is a $watch function
$scope.$watch($scope.OneTime,function(old,new)
{
// my function
});
The above $watch function will be fire whenever my (OneTime) object value has been changed.
But I won't to watch the object on every change, I just want to fire the $watch function when I change the my object on first time only.
I also tried something and find out a function from angular.js script file But I don't know what the below function doing exactly.
You can find this function from angular.js script file
function oneTimeWatchDelegate(scope, listener, objectEquality, parsedExpression) {
var unwatch, lastValue;
return unwatch = scope.$watch(function oneTimeWatch(scope) {
return parsedExpression(scope);
}, function oneTimeListener(value, old, scope) {
lastValue = value;
if (isFunction(listener)) {
listener.apply(this, arguments);
}
if (isDefined(value)) {
scope.$$postDigest(function () {
if (isDefined(lastValue)) {
unwatch();
}
});
}
}, objectEquality);
}
But am seeing a pretty word unwatch();inside the function . So i think I need to use $unwatch for the object when end of the $watch function. But I couldn't get anything about $unwatch concept anywhere in angular document. but I can see it on angular script.
I had some idea about manually stop this $watch function by this below way
var unwatch = $scope.$watch("OneTime", function() {
//...
});
setTimeout(function() {
unwatch();
}, 1000);
But I am thinking about if angular provide to unwatch function to stop the abject watching, it would be easy to handle in my whole application. So planed to take override something in angular.js file in my application. let me know if you have any idea about override angular.js script file to create $unwatch function as same as $watch function. And also let me know angular had any$unwatch function.
I think you need one way binding over here
you can achieve this br
{{::oneTime}}
in your html page One-time expressions will stop recalculating once they are stable, which happens after the first digest
var $unwatch=$scope.$watch('onetime',function(){
unregister();
}
AngularJS does already provide such function, exactly as you mentioned above. When you create a watcher, it returns you a function that may be used to stop watching it.
From the $rootScope.Scope documentation,
$watch(watchExpression, listener, [objectEquality]);
Returns: function() Returns a deregistration function for this listener.
The only thing you need to do to unwatch your object would be calling the returned function. You could call it inside your watch function so it will be executed at the first time your watcher is invoked.
var unwatch = null;
// start watching the object
var unwatch = $scope.$watch($scope.OneTime, function(old, new)
{
// my function
if (unwatch != null) {
unwatch();
}
});
This is my current implmentation to fire callback on customVar get change using $watch...
module.directive('mudirective', function() {
return {
scope: {
callback: '&'
},
template: '<h1>Hello</h1><button ng-click="changeVaar()>Click</button>"',
controller: function($scope) {
$scope.customVar = false;
$scope.changeVaar = function() {
// some large logical execution
// which set customeVar
$scope.customVar = '';//some value assgined
};
},
link: function($scope) {
$scope.$watch('customVar', function() {
$scope.callback();
});
}
};
});
But i would like to replace this $watch with setter...
Can anybody has idea how could it be possible?
OR
Other option to avoid $watch function but fire callback on customVar changes.
But callback should be fire once it is confirmed that customVar
has changed in directive itself.
First, I will answer the comments under the question. I had this use case when I saw a controller putting a watcher on a scope value only to detect changes while the value was changed only by assignments inside the controller itself...
The watch was calling a function updating the UI depending on the assigned value (null or not, whatever).
Of course, we could call this function on each assignment. Or replace the watch with a function setting the value given as parameter, and calling this function. But somehow, using a setter was more "transparent", made a minimal set of changes, and you are sure not to miss an assignment.
On hindsight, it is similar to the way MobX works (go see this library if you have complex dependency watching to do).
Second, here is how to do it:
Object.defineProperty($scope, 'watchedValue',
{
set(newValue) { $scope._watchedValue = newValue; this.doSomethingWith(newValue); },
get() { return $scope._watchedValue; },
});
I have a little trouble with passing value from one function to another in one angular controller.
i have event
onTimeRangeSelected: function (args) {
$scope.dayPilotCal.clearSelection();
$scope.createNewEventModalWindow(args);
},
event call function
$scope.createNewEventModalWindow = function(args)
{
console.log('create new event dialog');
$rootScope.newEvent.start = args.start.value;
console.log($rootScope.newEvent.start);
ngDialog.open({
......
});
}
than i handle dialog confirm button click event
<button
type="button"
class="ngdialog-button ngdialog-button-primary"
ng-click="btnCreateEventClicked()"
>Create</button>
and call function
$scope.btnCreateEventClicked = function(){
console.log('btn create event clicked');
ngDialog.close();
console.log($rootScope.newEvent.start);
};
so that my problem - in first case console.log($rootScope.newEvent.start); print to console real date. But in the second function console.log($rootScope.newEvent.start); print into console 'undefined' value.
all code are in the same controller. And in the first lines of controller i define my global variable $rootScope.newEvent={};
Please help me in that problem.
Global variables makes testing the code really difficult. Because any function can have access to the global scope. In your example I would assume their is another part of your coding that changes $rootScope.newEvent.
If this variable has to be globally available I would suggest to use a service.
If their is no need for this var to be globally accessible, than just change $rootScope.newEvent to $scope.newEvent.
I am updating the value of a parent variable from a directive's isolated scope using $scope.$parent.parentvariable.field = newfield.
When I console like console.log($scope.$parent.parentvariable.field), the field contains new values as seen in console. However, the template which should get updated (as it is bound with field) is not getting updated.
Using $apply() as $scope.$parent.$apply() throws $digest already in use error.
What is going wrong here?
Trying to do something like:
$scope.$parent.group_levers.levers.forEach(function (lv,indexLever) {
if (lv.RFLeverId == lever.RFLeverId) {
lv.description.leverValue.forEach(function (leverVal, indexLeverVal) {
if (leverVal.RFLeverValueId == splashResponseRaw.levers[0].description.leverValue[0].RFLeverValueId) {
$scope.$parent.group_levers.levers[indexLever].description.leverValue[indexLeverVal] = splashResponse;
//$scope.$parent.$apply();
}
})
}
})
$timeout(function () {
$scope.$parent.$apply();
}, 10)
try this. after a small fraction of milliseconds run apply.
$timeout(function(){
scope.$apply();
},100)