Jimi
Jimi

Reputation: 1897

angular1 - angular.js:11655 RangeError: Maximum call stack size exceeded

I have a directive that has a controller with a $http call to an endpoint. I'd like to take the results of that server call and then display them in my template. If I have a single value inside my template, and then set it explicitly, it all works fine. If I try to bind the template to the server call then I get the error mentioned above. Do I need to use the $compile service for this to work?

thanks in advance

Final result with compilation

function mydirective(myservice,$compile) {

    return {
        restrict: 'ACE',
        scope: {
            url: '=',
            title: '=',
        },

        controllerAs: 'ctrl',
        bindToController: true,
        controller: ['$scope', function($scope) {
            myservice.init('http://jsonplaceholder.typicode.com/posts')
                .then(function(data) {
                    $scope.postRequest(data);
                });
            $scope.postRequest = function(val) {
                this.items = val;
                this.title = val[0].title;
            };
        }],
        link: function ($scope, $el, $attr  ) {

            var template = '<div class=\"test\">{{this.title}}</div>' +
                '<div class=\"tes\" ng-repeat=\"item in this.items\">'+
                '<div class=\"test1\">{{item.title}}</div>'+
                '</div>';

            var e = $compile(template)($scope);
            $el.after(e);
        }
    };
}

Upvotes: 0

Views: 871

Answers (1)

Claies
Claies

Reputation: 22323

Here is a refactored version of your directive. Because you are using controllerAs, the reference to $scope can be removed entirely. Also, a variable ctrl is created as an alias to the controller, for consistent access to the controller from inside callback functions. Finally, the link function is removed and the template has been adjusted to reference ctrl instead of this.

The error

RangeError: Maximum call stack size exceeded

is a result of using this in the template, which is referring to the DOM rather than the controller, in conjunction with $compile, essentially compiling the DOM into itself.

function mydirective(myservice, $compile) {

  return {
    restrict: 'ACE',
    scope: {
      url: '=',
      title: '=',
    },
    controllerAs: 'ctrl',
    bindToController: true,
    controller: function() {
      var ctrl = this; //alias reference for use inside controller callbacks
      myservice.init('http://jsonplaceholder.typicode.com/posts')
        .then(function(data) {
          ctrl.postRequest(data);
        });
      ctrl.postRequest = function(val) {
        ctrl.items = val;
        ctrl.title = val[0].title;
      };
    },
    template: '<div class=\"test\">{{ctrl.title}}</div>' +
      '<div class=\"tes\" ng-repeat=\"item in ctrl.items\">' +
      '<div class=\"test1\">{{item.title}}</div>' +
      '</div>'
  };
}

Please note this code hasn't been tested.

Upvotes: 1

Related Questions