Reputation: 1819
How to get an Angular directive to render when added to the dom outside of Angular?
I’m in the process of slowly introducing angular to an existing codebase. There exists a table with a bunch of rows in the dom. Each row contains a spinner element, which is controlled by a directive:
<tr>
<td>stuff</td>
<td><div spinner></div></td>
<tr>
joyableApp.directive('spinner', [function() {
return {
templateUrl: 'spinner.html',
}
}]);
Now- when the <div spinner>
is in the dom on page load, the spinner directive is correctly activated and the spinner.html
template is properly rendered inside that div.
However, there’s a button on this page that will add additional rows to the table. The query governing that button is:
$(“#new-row-button”).click(function(e) {
$.get(“/get_new_row_content”, function(data) {
$(“#table tbody”).append(data);
});
});
The html returned from /get_new_row_content
is pretty much just the html shown above, and contains <div spinner>
. Dom inspection verifies that the spinner element is added to the page. However, the spinner.html
template is not getting rendered. The spinner directive isn’t getting triggered when this new row is added.
Note that this jquery code is not in any controller, service, factory, or any other angular thing.
So, how do I get the angular directive to pick up the new row?
I suspect that the correct answer is to make the whole page be controlled by angular, including the ‘add row’ button, but I don’t have the time to do that. I need a short-term bridge between angular and the existing code.
TLDR: How do I get an angular directive to trigger for a dom element that was dynamically to the page from outside of angular?
Upvotes: 0
Views: 555
Reputation: 5254
The correct thing to do would be to have the have an ng-repeat.
<tr ng-repeat="rowData in allRowData">
The button could then have an an ng-click that adds new data to the allRowData array. and update the to display the data you want to see in rowData.
The above would be the correct way to implement angular for your use. Ignoring that advice do build and add content on the fly you can do the following outside angular.
var elem = angular.element(jQuery(“#table tbody”));
elem.injector().invoke(function($compile){
elem.append($compile(html)(elem.scope()));
})
Upvotes: 2
Reputation: 873
You have to use the $compile service and then inject the result into your page:
$(“#new-row-button”).click(function(e) {
$.get(“/get_new_row_content”, function(data) {
var $injector = angular.injector(['ng','any other needed modules']);
$injector.invoke(function($rootScope,$compile){
$(“#table tbody”).append($compile(data)($rootScope));
});
});
});
Upvotes: 1