7

On the docs I saw an example of compiling "something" added later.

var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
$(document.body).append($div);

angular.element(document).injector().invoke(function($compile) {
  var scope = angular.element($div).scope();
  $compile($div)(scope);
});

I've added this code on a jquery ready function, but I have two problems:

First is an error: Argument 'MyCtrl' is not a function, got undefined.

The second is that I don't know how to make that content.label works! I've added it to the scope but it doesn't work. How should I call my controller to see working the data binding of content.label?

MY FINAL MODIFIED CODE IS:

var app = angular.module('app',[]);

    $(function(){

        app.controller('MyCtrl',function($scope){
            $scope.content = 123;
        });

        var $div = $('<div ng-controller="MyCtrl">{{content}}</div>');
        $(document.body).append($div);

        angular.element(document).injector().invoke(function($compile) {
          var scope = angular.element($div).scope();
          $compile($div)(scope);
        });

    });
stackoverflow
  • 1,303
  • 2
  • 21
  • 36
  • Does your code above have errors? (Such as `$scope.content` isn't defined?) - are you including the JS? – tymeJV Nov 19 '15 at 14:41
  • please take a look at the edit. The only error is the one shown above – stackoverflow Nov 19 '15 at 14:46
  • You can derive from the html that label is a property of content. ($scope.content.label = "something" or $scope.content = { label : "something" };) – skubski Nov 19 '15 at 14:48
  • ok, I know that, but how can I make it works? – stackoverflow Nov 19 '15 at 14:49
  • Is scope null or undefined when you assign it? – Captain Delano Nov 19 '15 at 15:09
  • It works [here](http://plnkr.co/edit/ttYwVHxMms9b3r4dhc1o). – skubski Nov 19 '15 at 15:10
  • @skubski have you read my desc? On the docs.... "something" **added later**. I`ve also shared the docs link to see more info "This is fairly rare but could be the case if a third party library is injecting the markup" – stackoverflow Nov 19 '15 at 15:16
  • Yeps, you are right. Whenever it is added after the bootstrap or by a third party library a digest/apply needs to be triggered to tell angular that it got changed from outside of its system. – skubski Nov 19 '15 at 15:44

1 Answers1

4

UPDATE

You should start a digest cycle after compiling new markup, in order to build all bindings and fire watchers. This can be done by calling scope.$digest(); :

$compile($div)(scope);
scope.$digest();

The result should look like:

var app = angular.module('app',[]);
  app.controller('MyCtrl',function($scope){
      $scope.content = 123;
  });

  angular.element(document).ready(function () {
      var $div = $('<div ng-controller="MyCtrl">{{content}}  </div>');
      $(document.body).append($div);

      angular.element(document).injector().invoke(function($compile) {
        var scope = angular.element($div).scope();
        $compile($div)(scope);
        scope.$digest();
      });

  });

http://plnkr.co/edit/dDNBxf8SowKTPgnVj0tF?p=preview

Alexandr Lazarev
  • 12,554
  • 4
  • 38
  • 47