Reputation: 3321
It is complex to explain, but I'll try to.
http://plnkr.co/edit/PrVXRvHAC7wtgHUEU1HB?p=preview
This example works as I need, I just don't like the way I achieved this.
I'll try to explain what you see in the example.
<repeater>
<item name="Hello item">
<h4>Hello</h4>
<p>Lorem ipsum dolor sit amet</p>
</item>
<item name="Worlditem">
<h4>World</h4>
<em>Mauris elementum elementum enim at suscipit.</em>
</item>
</repeater>
<item>
directive should "register" itself to the parent repeater
as available_item
. And it shouldn't be shown at the moment.
<repeater>
directive should print menu of available items, and after clicking on menu item, it should add item's template to it's content. For example repeater
template may look something like this:
<div>
<ul>
<li ng-repeat="item in available_items">
<a href="javscript:;" ng-click="add2content(item)">{{item}}</a>
</li>
</ul>
<div id="content">
<div ng-repeat="item in content_items track by $index">
<ng-include src="item"></ng-include>
</div>
</div>
</div>
So what don't I like in my working plnkr.co example?
I don't like that I must include <div ng-transclude></div>
in my repeater.html
, otherwise <item>
's won't be compiled any more. But I don't need to print items at page load - they are just templates. I have set <items>
template to empty string, but in source I see empty <item>
tags, and I don't like this..
Actually I am not sure what I don't like there, but it feels like everything is hard-coded
there, isn't it?
If repeater
's directive would be compiled in this order:
item
directives, and they could register itself to repeaterng-transclude
I'm sure It's impossible to do this. And I'm not sure what I don't like in my code, but I hope you will see other ways to improve my code.
Thank you very much!
P.S. I know I can replace <item>
directive with some <script type="text/ng-template" id="">
tags, but I need <item>
as provided in my example.
Upvotes: 0
Views: 656
Reputation: 50365
This plunkr does what you want to achieve, except the parts you don't like (i.e. dummy <transclude>
tag and empty <item>
tags). I've also cleaned up hacks like storing HTML in attribute, return empty template, pollute template cache...
The key element of this solution is using the $transclude
service to compile and link directives declared in the transcluded content. The entire updated script is below.
script.js
angular.module('repeaterApp', [])
.directive('repeater', function() {
return {
restrict: 'E',
transclude: true,
scope: {},
templateUrl: 'repeater.html',
controller: function($scope, $element, $transclude) {
var available_items = $scope.available_items = [];
var content_items = $scope.content_items = [];
$scope.add2content = function(item) {
content_items.push(item);
};
$scope.add2available = function(item) {
available_items.push(item);
};
$transclude($scope);
}
};
})
.directive('item', function($templateCache, $sce) {
return {
restrict: 'E',
link: function(scope, element, attrs) {
scope.add2available({
name: element.attr('name'),
html: $sce.trustAsHtml(element.html())
});
}
};
});
repeater.html
<div>
<ul>
<li ng-repeat="item in available_items">
<a href="javscript:;" ng-click="add2content(item)">{{item.name}}</a>
</li>
</ul>
<div id="content">
<div ng-repeat="item in content_items track by $index"
style="background: #f4f4f4; padding: 5px; margin: 5px; clear: both;"
ng-bind-html="item.html">
</div>
</div>
</div>
index.html
<repeater>
<item name="Hello item">
<h4>Hello</h4>
<p>Lorem ipsum dolor sit amet</p>
</item>
<item name="Worlditem">
<h4>World</h4>
<em>Mauris elementum elementum enim at suscipit.</em>
</item>
</repeater>
Upvotes: 1