When composing my view out of various HTML partials, I prefer the declarative approach of placing an ng-include
directive in my markup.
However a third party widget for a slideShow / carousel that I need to populate with items dynamically does not play well with the dynamic DOM changes of ng-repeat
and ng-include
(the third party widget will either accept a set of child nodes to be present in the DOM at the point in time the widget is initialized, or accept that new items are added programmatically by calling an addItem
function).
<!-- this will not work properly, the items collection changes dynamically -->
<div id="slideShowHost">
<div class="slideShowItem"
ng-repeat="item in controller.items"
ng-include="'templates/slideShowItem.html'">
</div>
</div>
Therefore I will replace the slideShowHost content with equivalent code in my controller. I use RequireJS to load the content of templates/slideShowItem.html as one string, and jQuery to create corresponding nodes from it for all my items. But this will not suffice as I use angular directives in the slideShowItem template that need to come to life.
// I'm using typescript here, but answers may as well use untyped javascript
var slideShowHost = $("#slideShowHost").acmeSlideShow();
require(["slideShowItemTemplate-html"], (itemTemplate: string) =>
{
for (var i = 0; i < this.items.length; i++)
{
let initializedItem = this.initAngularDependentItem(this.items[i], itemTemplate);
slideShowHost.addAcmeSlideShowItem( initializedItem );
}
});
...
private initAngularDependentItem(itemModel: any, template: string): any
{
let itemView = $(template);
// we have to create a scope here containing the itemModel
// and we need to init the angular directives inside itemView
return itemView;
}
Which code would be a correct and reliably working replacement for any ng-include
where the included partial may use any angular directives and even nested ng-includes?
You need to use $compile like this:
app.controller(function($scope, $compile) {
var link = $compile(template);
$('...').append(link($scope));
});