Search code examples
javascriptangularjsangularjs-scope

How to render an AngularJS template to a String without causing InProg error?


I am trying to write a service which renders a given template and scope to a string.

This is the code:

utilModule.factory('CompilerService', ['$compile', '$templateCache',
    function ($compile, $templateCache) {
        return {
            renderTemplateToString: function(templateName, scope) {
                var template = $templateCache.get(templateName);
                var linkFn = $compile(template);
                var linkedContent = linkFn(scope);
                scope.$apply();

                return linkedContent.html();
            }
        }
    }]);

When I call this however, I am getting the angular InProg err, caused by the call to $apply():

https://docs.angularjs.org/error/$rootScope/inprog

I am calling $apply() in order for the variables to be substituted within the template before retrieving the html.

Any ideas on how to achieve this without the InProg error?


Solution

  • You have two options:

    if ( !scope.$$phase )
        scope.$apply();
    

    this is checking if the code is being executed during a $digest cycle.

    However, $timeout is preferred:

    $timeout( function(){
      var template = $templateCache.get(templateName);
                    var linkFn = $compile(template);
                    var linkedContent = linkFn(scope);
    }, 0)
    

    EDIT: in order to use premises, you should do something like that:

        renderTemplateToString: function(templateName, scope) {
                var deferred = $q.defer();
                $timeout(function(){
                   var template = $templateCache.get(templateName);
                   var linkFn = $compile(template);
                   var linkedContent = linkFn(scope);
                   scope.$apply();
                   deferred.resolve( linkedContent.html() );
                }, 0);
    
                return deferred.promise;
        }
    

    $timeout is waiting to the $digest to finish before executing