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
Loading an AngularJS controller dynamically
The answer to this question fixed my problem. Since I need to create the controllers after the content was added to the DOM. This fix requires me too register controllers after I have declared it. If someone has an easier solution pleace chip in.
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.
Your approach doesn't seem right. You are usinging jQuery and Angular together in an inappropriate way that is likely to have conflicts.
Angular's built in template support is the best way to do this either using ng-include or you can use Angular's routing and along with ng-view. The documentation is here:
http://docs.angularjs.org/api/ng.directive:ngInclude
http://docs.angularjs.org/api/ngRoute.directive:ngView
The simplest possible thing would be to just set the ng-include to the url string:
<div ng-include="'ajax.html'"></div>
If you actually need it to load dynamically when you do something then this is a more complete solution for you:
http://plnkr.co/edit/a9DVEQArS4yzirEQAK8c?p=preview
HTML:
<div ng-controller="InitCtrl">
<p>{{ started }}</p>
<button ng-click="loadTemplate()">Load</button>
<div class="content" ng-include="template"></div>
</div>
Javascript:
var myApp = angular.module('myApp', [])
.controller('InitCtrl', function($scope)
{
$scope.started = 'App is started';
$scope.loadTemplate = function() {
console.log('loading');
$scope.template = "ajax.html";
}
}).controller('AfterCtrl', function($scope)
{
$scope.loaded = 'Is now loaded';
});
One other gotcha that leads to this Bootstrapping error is the nginclude or ngview scenarios where your dynamic html includes script references to angular js.
My html below was causing this issue when it got injected into an existing Angular page. The reference to the angular.min.js caused Angular to rebootstrap:
<div id="fuelux-wizard" class="row-fluid" data-target="#step-container">
<ul class="wizard-steps">
<li data-target="#step1">
<span class="step">1</span>
<span class="title">Submit</span>
</li>
<li data-target="#step2">
<span class="step">2</span>
<span class="title">Approve</span>
</li>
<li data-target="#step3">
<span class="step">3</span>
<span class="title">Complete</span>
</li>
</ul>
</div>
<script src="/Scripts/Angular/angular.min.js"></script>
<script type="text/javascript">
angular.element('#requestMaster').scope().styleDisplayURL();
</script>