Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular bootstrapping after load of html

Tags:

html

angularjs

I first initialize my app with ng-app="myApp" in the body tag and this works fine for all angularized-html that is loaded on first page load.

Later on I have some code that loads angularized-html in to the DOM.

In angular 1.08 I could just run angular.bootstrap($newLoadHTML, ["myApp"]) after the load and it would work; where $newLoadHTML is the newly added HTML grabbed with jQuery.

In angular 1.2 this does no longer work:(

Error: [ng:btstrpd] App Already Bootstrapped with this Element '' http://errors.angularjs.org/1.2.0-rc.2/ng/btstrpd?p0=%3Cdiv%20ng-controller%3D%22AfterCtrl%22%3E

I am getting this error which I understand, but I don't know how to solve it.

What I need to be able to do is load angularized-html and then make angular aware of it.

Here is a plunker to illustrate it: http://plnkr.co/edit/AHMkqEO4T6LxJvjuiMeT?p=preview

like image 491
Christian Avatar asked Oct 17 '13 10:10

Christian


1 Answers

I will echo what others have mentioned: this kind of thing is generally a bad idea, but I also understand that you sometimes have to work with legacy code in ways you'd prefer not to. All that said, you can turn HTML loaded from outside Angular into Angular-bound views with the $compile service. Here's how you might rewrite your current example to make it work with $compile:

// We have to set up controllers ahead of time.
myApp.controller('AfterCtrl', function($scope)  {
  $scope.loaded = 'Is now loaded';
});

//loads html and afterwards creates a controller
$('button').on('click', function() {
  $.get('ajax.html', function(data) {

    // Get the $compile service from the app's injector
    var injector = $('[ng-app]').injector();
    var $compile = injector.get('$compile');

    // Compile the HTML into a linking function...
    var linkFn = $compile(data);
    // ...and link it to the scope we're interested in.
    // Here we'll use the $rootScope.
    var $rootScope = injector.get('$rootScope');
    var elem = linkFn($rootScope);
    $('.content').append(elem);

    // Now that the content has been compiled, linked,
    // and added to the DOM, we must trigger a digest cycle
    // on the scope we used in order to update bindings.
    $rootScope.$digest();

  }, 'html');
});

Here is an example: http://plnkr.co/edit/mfuyRJFfA2CjIQBW4ikB?p=preview

It simplifies things a bit if you can build your functionality as a directive instead of using raw jQuery--you can inject the $compile and $rootScope services into it, or even use the local scope inside the directive. Even better if you can use dynamic binding into an <ng-include> element instead.

like image 114
Michelle Tilley Avatar answered Sep 28 '22 09:09

Michelle Tilley