Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggle or disable/re-enable an AngularJS watch

I need to be able to ignore specific watches while performing specific tasks. Here is the scenario.


I have a couple watchers on fields which are being used to calculate a "totals" field.

All of these fields can be manually modified, which will trigger the watches which calculate the "totals" field.

The fields can also be loaded from a saved state, which also triggers the watches which calculate the "totals" field.

The "totals" field can also be manually overridden, saved, and loaded.

The problem occurs when a manually overridden "totals" field is loaded with the other fields. The watches which recalculate the "totals" are triggered, and overwrite the manually overridden "totals".

I need to be able to ignore watches while the load is occurring. Is there any way to to this?

I know a watcher can be disabled using the de-registration function that is passed back when you create a watch, but when you re-create the watcher is still knows that the data it was watching has changed.

Note: This is an oversimplified description of the business logic surrounding the issue. Not being able to disable a watch would require a significant amount of work.

Here is a fiddle showing the problem: jsfiddle.net/vGWZy/1/

like image 635
Conan Morris Avatar asked Feb 15 '23 00:02

Conan Morris


1 Answers

Your can store watcher's callbacks and disabler in special service, and use binding and unbinding of them with service method's

Example with your code http://jsfiddle.net/snicksnk/66osj8zm/

//Service for working with watcher's binding
var watchService = {
    watchers: {},
    create: function(name, callback){

        watchService.watchers[name] = 
        {
            'callback': callback,
            'disableCallback': null
        };
    },
    enable: function($scope, name){
        if (typeof watchService.watchers[name]['callback'] !== 'function'){
            return;
        }
        watchService.disable(name);
        var watcher = watchService.watchers[name]['callback'];
        watchService.watchers[name]['disableCallback'] = $scope.$watch(name, watcher, true);


    },
    disable: function(name){
        if (typeof watchService.watchers[name]['disableCallback'] !== 'function'){
            return;
        }
        watchService.watchers[name]['disableCallback']();
    }
};

//Creating of watcher's callbacks, instead of using $scope.$watch directly
watchService.create('item.value1',  function() {
    $scope.item.total = $scope.item.value1 * $scope.item.value2;
});


watchService.create('item.value2',  function() {
    $scope.item.total = $scope.item.value1 * $scope.item.value2;
});



//Wathcers enabler
$scope.enableWatchers = function(){
    watchService.enable($scope, 'item.value1');
    watchService.enable($scope, 'item.value2');
};

//Wathcers disable
$scope.disableWatchers = function(){
    watchService.disable('item.value1');
    watchService.disable('item.value2');
};
like image 96
yurisnk Avatar answered Mar 02 '23 04:03

yurisnk