Damian Pieczyński
Damian Pieczyński

Reputation: 3336

AngularJS - after $compile the call new function in html is run many times

the problem is, i have simple directive to get the data from backed (JSP page) ( which have a call function from angular to set some values to js model, but when i get response the call function is x times....

here is the sample

http://plnkr.co/edit/OISkbF

when you see console log, and click "Load form JSP" button,

first it's 3 times call the methods, next it's 6 time...

here is topic in google grupe angularJS https://groups.google.com/d/msg/angular/18a_Iqkdbtk/eDuZ4OLfwJMJ

Upvotes: 2

Views: 3959

Answers (1)

matys84pl
matys84pl

Reputation: 8334

I've fixed few things in your example, now it only calls the functions twice (this is actually correct, because this is how $digest works, it will call the bindings until there is no change, so at least 2 times each.

Working fork of your plunker: http://plnkr.co/edit/Aw6S6T?p=preview

The key part is here:

app.directive('angularHtmlBind', function($compile, $http) {
return function(scope, elm, attrs) {
    var $elm = $(elm),
        url = 'search.jsp',
        html,
        currentScope;

    function getHTML(url) {
      $http.get('search.jsp').success(function(data) {
        html = data;
        currentScope = scope.$new();
        $elm.html(html);         
        $compile($elm.contents())(currentScope);       
        }).error(function(data, status, headers, config) {    
            console.log(data);
        }); 
    }        
    scope.$watch(attrs.shown, function(value) {                           
      if (value) {            
        getHTML(url);            
      } else if (currentScope) {            
        $elm.contents().remove();            
        currentScope.$destroy()            
      }          
    });
};
});

There were 2 problems with your implementation, you were:

  1. calling $http and expect the result in the line below, this is an async call, so I've moved your $compile to the success handler
  2. reusing the the same scope each time the jsp file is loaded, so passing the same object to newly created controller (each time you $compile it creates a new instance of your controller). I'm creating a new scope for each jsp file and then destroying it when it's not used any more.

Of course this example could have been improved even more but I'm assuming that you load the sample file multiple times just to illustrate the problem;) If not, then call it once and then use the html var which stores the content.

Upvotes: 2

Related Questions