Reputation: 111
I've defined the following directive which wraps the pagination
directive provided by UI Bootstrap
angular.module('my-module')
.directive('myPagination', ['$filter', '$window', function ($filter, $window) {
return {
restrict: 'EA',
scope: {
itemsPerPage: '=',
totalItems: '=',
page: '='
},
link: function (scope, element, attrs) {
scope.hiddenElement = true;
var totalMargin = 200, widthByElement = 41;
scope.getWindowDimensions = function () {
return {
'w': element.width()
};
};
scope.$watch(scope.getWindowDimensions, function (newWidth, oldWidth) {
// calculate how many page buttons fit in the pagination horizontal bar
scope.maxSize = parseInt($filter('number')((newWidth.w - totalMargin) / widthByElement, 0));
}, true);
angular.element($window).bind('resize', function () {
// "$digest already in progress" thrown by the following line
scope.$apply();
});
},
template: '<div class="text-center paginationSelfCare" ng-show="totalItems > itemsPerPage">' +
'<pagination ng-show="totalItems/itemsPerPage <= maxSize" total-items="totalItems" items-per-page="itemsPerPage" ng-model="page" max-size="maxSize" class="pagination pagination-sm" ></pagination>' +
'<pagination ng-show="totalItems/itemsPerPage > maxSize" total-items="totalItems" boundary-links="true" direction-links="true" previous-text="<" next-text=">" first-text="<<" last-text=">>" items-per-page="itemsPerPage" ng-model="page" max-size="maxSize" class="pagination pagination-sm" ></pagination>' +
'</div>'
};
}]);
If this directive is running in one browser tab (A), and I switch to a different tab (B), then when I switch back to A, I see the following error in the browser console:
Error: [$rootScope:inprog] $digest already in progress http://errors.angularjs.org/1.4.4/$rootScope/inprog?p0=%24digest minErr/<@http://127.0.0.1:9000/bower_components/angular/angular.js:68:12 beginPhase@http://127.0.0.1:9000/bower_components/angular/angular.js:16273:1 $RootScopeProvider/this.$gethttp://127.0.0.1:9000/bower_components/angular/angular.js:16014:11 .link/<@http://127.0.0.1:9000/scripts/directives/pagination.js:30:11
Line 30 of pagination.js
is the line marked with a comment above
scope.$apply();
Is there something I can check before calling scope.$apply();
in order to avoid this issue? I'm running Angular version 1.4.4
Upvotes: 2
Views: 3053
Reputation: 136134
You could try $socpe.$applyAsync()
instead of $scope.$apply()
which will never conflict with currently running digest cycle.
$apply
on $scope
directly tried to run digest cycle when you run it directly. It doesn't check for if any digest cycle is in progress, and you run the digest loop, it throws $digest already in progress
.
Though you could fix this issue by using wrapping your code $timeout
function, but I'd prefer to go for $applyAsync
method of scope
.
$timeout
does run digest
cycle but before running it, it checks for if any digest is in progress, then run place this digest
cycle call in queue and run it once the running digest cycle complete.
$applyAsync
is a performance wise improved version of running digest cycle, when you ran this method, it first check for any digest cycle is running or not. if there any running digest cycle found it place that block of in that digest cycle (That means you reduced one digest cycle).
Upvotes: 6
Reputation: 9476
Your watch is very strange. This is usual way:
angular.element($window).bind('resize', function () {
// There are a lot of resize events, we do not need to change smth on each
// Once per some time is ok.
if (attrs.lastResize) {
$timeout.cancel(attrs.lastResize)
}
attrs.lastResize = $timeout(function() {
// actual code like
// like scope.maxSize = calc();
}, 75)
});
You dont need apply here, since you have $timeout.
Upvotes: 0