0
votes

I'm calculating the min-height for an html element with a directive and when I try to update the parent scope value via scope.$apply() i get this error: $digest already in progress

I know there are bunch of topics like this but none of the given solutions work for me. This is my view:

<header id="headerFR"> header content here </header>
<main id="contentFR" main-min-height ng-style="{'min-height': calcMinHeight}">
    {{calcMinHeight}}
    <welcome:info></welcome:info>
    <button type="button" class="appTOS">{{tosBtnLbl}}</button>
</main>
<footer id="footerFR"> footer content here </footer>

... the ctrl:

FIRSTRUN.controller('WelcomeCtrl', ['$scope', '$location', function($scope, $location){
    ...
    $scope.calcMinHeight;
    ...
}]);

and my directive:

FIRSTRUN.directive('mainMinHeight', ['$window', function($window){
    return{
        restrict: 'A',
        scope: { calcMinHeight: '=' },

        link: function(scope, el, attrs){
            var headerHeight = angular.element('header').outerHeight();
            var windowHeight = angular.element($window).height();

            var mainMinHeight = windowHeight - headerHeight;
            scope.$parent.calcMinHeight = mainMinHeight + 'px';
            scope.$apply();

        }
    }
}])

I can always update parent scope value with scope.$parent.calcMinHeight, but in this case the directive's scope rules won't work (for eg. if i'll want to isolate the scope via '@', the ctrl will still receive the update).

Also, I can set the min-height value via angluar.element(el).css('min-height', mainMinHeight+'px'), but I want to do it in angular way.

Where's the problem?
*Using angular 1.3.5 for any matter.

Answer:

To solve the error was enough to remove the scope.$apply() line as I was already in a $digest loop, as @enzey & @Andrew Counts said.
Also, I was misunderstanding the way scopes are working and I needed a better overview, which I found it here.
I just thought that directives can have their own scopes, like ctrls, and that was the issue from the start.

1
As you are already in a digest just remove scope.$apply(). - Enzey
scope.$apply() is only necessary if you need to trigger updates manually. If there is a digest already in progress, then the call to scope.$apply() is redundant anyway. does the page work correctly without the call? - Claies
yes, the page works well without the $apply() fn, but my concern was that if i use scope.$parent it will update the ctrl value even if I restrict the scope to be isolated with '@'. Did a test with '@' and $watch on 'calcMinHeight' in my ctrl and the old and new value are the same & updating even with '@' - tbutcaru

1 Answers

1
votes

This error will happen if your code calls $apply during a digest. One possible workaround is to wrap your code in a call to the $timeout service:

//add $timeout to controller parameters
$timeout(function(){
  ///...
  scope.$parent.calcMinHeight = mainMinHeight + 'px';
  //timeout will automatically trigger an $apply
}, 0);

This will give the added benifit of allowing the browser to render before performing the height calculation