rottendevice
rottendevice

Reputation: 2879

Compiling a directive results in error: $apply already in progress

This seems pretty simple.

In Angular JS, I'm trying to compile a directive when the user clicks a link on the page. To do this, I have an ng-click handler.

<a ng-switch-when="grade" id="{{ item.gb_class_id }}" ng-click="showHWClick(item.gb_class_id, item.period_id, item.student_id)" href="">{{ item.grade }}</a>

... and inside my controller, I define the ng-click function:

$scope.showHWClick = function(classId) {

        $('#' + classId).parent().parent('.grade-row').after($compile('<tr><td class="homework-row" colspan="9"><progress-report /></td></tr>')($scope));

    }

And here's my directive:

.directive('progressReport', function() {
    return {
        restrict: 'E',
        templateUrl: 'Content/app/dashboard/progressreport.html'
    }
});

So really, I'm just compiling a template when the user clicks a link. The problem is, this returns the following error messages:

Error: $apply already in progress at Error (<anonymous>) at beginPhase (http://localhost:81/content/lib/angular/angular.js:8334:15) at Object.Scope.$apply (http://localhost:81/content/lib/angular/angular.js:8136:11) at Object.$delegate.__proto__.$apply (http://localhost:81/#/:855:30) at done (http://localhost:81/content/lib/angular/angular.js:9170:20) at completeRequest (http://localhost:81/content/lib/angular/angular.js:9333:7) at XMLHttpRequest.xhr.onreadystatechange (http://localhost:81/content/lib/angular/angular.js:9303:11) at http://localhost:81/content/lib/angular/angular.js:9312:11 at sendReq (http://localhost:81/content/lib/angular/angular.js:9146:9) at $http (http://localhost:81/content/lib/angular/angular.js:8937:17)

Error: Failed to load template: Content/app/dashboard/progressreport.html at Error (<anonymous>) at http://localhost:81/content/lib/angular/angular.js:4549:17 at http://localhost:81/content/lib/angular/angular.js:8957:11 at wrappedErrback (http://localhost:81/content/lib/angular/angular.js:6855:57) at http://localhost:81/content/lib/angular/angular.js:6931:53 at Object.Scope.$eval (http://localhost:81/content/lib/angular/angular.js:8057:28) at Object.Scope.$digest (http://localhost:81/content/lib/angular/angular.js:7922:25) at Object.$delegate.__proto__.$digest (http://localhost:81/#/:844:31) at Object.Scope.$apply (http://localhost:81/content/lib/angular/angular.js:8143:24) at Object.$delegate.__proto__.$apply (http://localhost:81/#/:855:30)

The failed to load template error is strange, because I've quadruple checked the location of the template and it's correct. But I assume the error is a result of the first error message.

Does anyone know what's wrong? Thanks in advance.

EDIT: Here's the Plunker

EDIT 2: I'm using Angular 1.0.7.

Upvotes: 2

Views: 1970

Answers (2)

dherman
dherman

Reputation: 2892

You shouldn't be doing DOM manipulation outside of your directive to begin with. Rather than modifying the DOM, your showHWClick function should likely modify some property or object on the scope. Your templates would then be bound to that property and update like any other angular template.

This is all covered at http://docs.angularjs.org/tutorial/.

If I had to guess at what you're trying to accomplish, you might want to take a look at the ngIf directive that was introduced in 1.1.5 to conditionally add a piece of DOM ( not just show/hide it ).

Upvotes: 3

JQuery Guru
JQuery Guru

Reputation: 6963

I have modified the click event can you try with below code:

$scope.showHWClick = function(classId) {
        $timeout(function(){
            if (!$scope.$$phase) {
                $('#' + classId).parent().parent('.grade-row').after($compile('<tr><td class="homework-row" colspan="9"><progress-report /></td></tr>')($scope));
            }
        }, 500, false);

    }

Upvotes: 1

Related Questions