0

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);
        }
    };
}
Jimi
  • 1,867
  • 7
  • 31
  • 55
  • 1
    This post can tell you what that error means: http://stackoverflow.com/questions/22123769/rangeerror-maximum-call-stack-size-exceeded-why. You do not have to compile in this instance though. An example of when you might compile is say you did a GET request which returned some template...then you would need to manually compile it. – terpinmd Jun 17 '16 at 21:21
  • so essentially I need to push the results on to an array. How do I manually compile to see the values? – Jimi Jun 17 '16 at 21:48
  • you are mixing `$scope` and `controllerAs` in the same directive, and this will generally lead to cases of confusion. In particular, the `this` object inside the `$scope.postRequest` function is not a reference to the controller. Also, in your template, you should be using `ctrl` instead of `this`. – Claies Jun 18 '16 at 03:07
  • you actually don't need a `link` function at all in your directive; I'm going to refactor the directive for you in an answer. – Claies Jun 18 '16 at 03:09

1 Answers1

1

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.

Claies
  • 22,124
  • 4
  • 53
  • 77