Luigui Mendoza
Luigui Mendoza

Reputation: 21

init ng-controller when content is loaded dynamically in angular

I'm learning Angular I tried to init a controller after create a new content by ajax (with jQuery, maybe it's not a good idea but just I'm starting to learning step by step.)

this is my code.

angular.module('app').controller('TestController',function($scope){
   $scope.products = [{
      'code': 'A-1',
      'name': 'Product 01'
   }];

   $scope.clickTest = function(){
      alert('test');
   }
});

$.ajax({..})
.done(function(html){   
  angular.element(document).injector().invoke(function($compile){
    $('#content').html(html);
    var scope =  $('#content').scope();
    $compile($('#content').contents())(scope);

  });
});

In my html I use ng-repeat but not load nothing, however when I click in ng-click="clickTest" it works! and ng-repeat is loaded. this is my problem I need that the ng-repeat load when I load for first time.

Thanks.

Sorry for my bad english.

Upvotes: 2

Views: 1746

Answers (2)

PSL
PSL

Reputation: 123739

with jQuery, maybe it's not a good idea

Yes spot on


Now getting into your issue:- When you click on element with ng-click on the html, it works because it then runs a digest cycle and refreshes the DOM and your repeat renders. $Compile has already instantiated the controller and methods are available and attached to DOM. But there is one digest cycle that runs in angular after controller initialization, which renders data in DOM, and that does not happen in your case since you are outside angular.

You could do a scope.$digest() after compile to make sure element is rendered and digest cycle is run.

Also probably one more better thing would be to wrap it inside angularRootElement.ready function, just to make sure before the injector is accessed the element is ready, in your case enclosing it inside ajax callback saves you (the time for it to be ready) but better to have it.

Try:-

$.ajax({..})
.done(function(html){  
    var rootElement = angular.element(document);
      rootElement.ready(function(){
        rootElement.injector().invoke(function($compile){
          var $content = $('#content'),
              scope =  $content.scope();

          $content.html(html);
          $compile($content.contents())(scope);
          scope.$digest();
        });
      });
});

Sample Demo

Demo - Controller on dynamic html

Instead of getting html from the server you could create partials and templates, use routing , use angular ajax wrapper with $http etc... Well i would not suggest doing this method though - however based on your question you understand that already. There was a similar question that i answered last day

Upvotes: 4

Krishna Veeramachaneni
Krishna Veeramachaneni

Reputation: 2141

If you are not looking for a better way to do what you are doing, ignore the following.

The beauty of using frameworks like AngularJS and KnockoutJS (or many more) is that we don't have to worry about the timing of when the data loads. You just set up the bindings between the controller and the UI and once the data is loaded into the respective properties, these frameworks will take care of updating the UI for you.

I am not sure why you are trying to set up the UI using JQuery and waiting for the data to loaded first to do so but normally you will not have to do all that.

You can create a UI with ng-repeat and click bindings ,etc and make an ajax call to get the data from anywhere. Once the data is loaded, in the callback, just push the necessary data into the collection bound to the ng-repeat directive. That is all you will have to do.

Upvotes: 0

Related Questions