Last active
December 26, 2019 19:14
-
-
Save RadoMark/fbd501b26e0c389c4135 to your computer and use it in GitHub Desktop.
Watchers toggler directive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div ng-app> | |
<div ng-controller="TestCtrl"> | |
<ul ng-repeat="elements in array" watchers-toggler="toggler()"> | |
<li ng-repeat="element in elements">{{element}}</li> | |
</ul> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function TestCtrl($scope, $timeout) { | |
$scope.array = []; | |
for(var i = 0; i < 10; i++) { | |
$scope.array[i] = []; | |
for(var j = 0; j < 10; j++) { | |
$scope.array[i].push(j); | |
} | |
} | |
$scope.tog = false; | |
$scope.toggler = function() { return $scope.tog }; | |
// manipulate the $scope.tog variable and check number of watchers | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module | |
.directive('watchersToggler', ['$parse', '$timeout', function($parse, $timeout) { | |
return { | |
restrict: 'EA', | |
scope: { | |
toggler: '&watchersToggler', | |
refreshSuspensionOn: '=refreshHideOn' | |
}, | |
link: function($scope, element, attrs) { | |
var watchers = { | |
suspended: false | |
}; | |
$scope.$watch(function() { return $scope.toggler() }, function(newToggler, oldToggler) { | |
if(typeof newToggler == 'boolean') { | |
if(newToggler) { | |
//element.hide(); - with jquery dependency | |
element.css('display', 'none'); | |
suspendFromRoot(); | |
} else { | |
//element.show(); - with jquery dependency | |
element.css('display', 'block'); | |
resumeFromRoot(); | |
} | |
} | |
}); | |
$scope.$watch('refreshSuspensionOn', function(newVal, oldVal) { | |
if(newVal !== oldVal) refreshSuspensionFromRoot() | |
}, true); | |
function suspendFromRoot() { | |
if(!watchers.suspended) { | |
$timeout(function() { | |
suspendWatchers(); | |
watchers.suspended = true; | |
}) | |
} | |
} | |
function refreshSuspensionFromRoot() { | |
if(watchers.suspended) { | |
$timeout(function() { | |
suspendWatchers(); | |
}) | |
} | |
} | |
function resumeFromRoot() { | |
if(watchers.suspended) { | |
$timeout(function() { | |
resumeWatchers(); | |
watchers.suspended = false; | |
}) | |
} | |
} | |
function suspendWatchers() { | |
iterateSiblings($scope, suspendScopeWatchers); | |
iterateChildren($scope, suspendScopeWatchers); | |
}; | |
function resumeWatchers() { | |
iterateSiblings($scope, resumeScopeWatchers); | |
iterateChildren($scope, resumeScopeWatchers); | |
}; | |
var mockScopeWatch = function(scopeId) { | |
return function(watchExp, listener, objectEquality, prettyPrintExpression) { | |
watchers[scopeId].unshift({ | |
fn: angular.isFunction(listener) ? listener : angular.noop, | |
last: void 0, | |
get: $parse(watchExp), | |
exp: prettyPrintExpression || watchExp, | |
eq: !!objectEquality | |
}) | |
} | |
} | |
function suspendScopeWatchers(scope) { | |
if(!watchers[scope.$id]) { | |
watchers[scope.$id] = scope.$$watchers || []; | |
scope.$$watchers = []; | |
scope.$watch = mockScopeWatch(scope.$id) | |
} | |
} | |
function resumeScopeWatchers(scope) { | |
if(watchers[scope.$id]) { | |
scope.$$watchers = watchers[scope.$id]; | |
if(scope.hasOwnProperty('$watch')) delete scope.$watch; | |
watchers[scope.$id] = false | |
} | |
} | |
function iterateSiblings(scope, operationOnScope) { | |
while (!!(scope = scope.$$nextSibling)) { | |
operationOnScope(scope); | |
iterateChildren(scope, operationOnScope); | |
} | |
} | |
function iterateChildren(scope, operationOnScope) { | |
while (!!(scope = scope.$$childHead)) { | |
operationOnScope(scope); | |
iterateSiblings(scope, operationOnScope); | |
} | |
} | |
} | |
} | |
}]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I am using this directive but it's giving error for $compile:multidir Multiple Directive Resource Contention.