我有两个元素指令collection
和element
,应该像这样使用:
<collection>
<element/>
<element/>
</collection>
他们有模板:
collection.html
<header>header</header>
<div><ul>...</ul></div>
<footer>footer</footer>
element.html
<p>element</p>
...
应该用collection.html
代替element
用<li>..</li>
包裹每个<header>header</header>
<div>
<ul>
<li><p>element</p></li>
<li><p>element</p></li>
</ul>
</div>
<footer>footer</footer>
?
表达结果
element
在回顾问题背后的任务时,似乎{{1}}标签实际上是嵌套HTML的包装,这简化了事情。所以我添加了一个答案,描述了如何使用2级嵌套转换。
答案 0 :(得分:1)
ng-transclude
允许您在模板化指令中嵌套内容,使您能够在指令编译阶段操作被转换的元素。
在这种情况下,您需要使用transclude: 'element'
来转换整个 collection
元素。这是因为您需要以结构化方式对子元素进行操作(使用transclude: true
提供了一个所有子节点的平面数组,这些节点在此处不起作用。)
.directive('collection', function(){
return {
transclude: 'element',
使用翻译时,您的指令的编译功能中可以使用transclude
函数。此函数传递单个参数clone
,该参数为您提供已删除内容的克隆。使用transclude: 'element
时,整个指令元素将从页面中删除。这需要您稍后再添加。
compile: function(element, attrs, transclude) {
return {
pre: function(scope, element) {
transclude(scope, function(clone){
要开始操作我们将添加的内容,请迭代克隆的子元素,使用jqLite wrap
函数将它们与列表项标签包装在一起:
angular.forEach(clone.children(), function(el){
var el = angular.element(el);
el.replaceWith(el.wrap('<li></li>'));
});
然后从存储在传递给compile / link的元素中的HTML中创建并存储一个新的jqLite元素:
var html = angular.element(element.html());
使用jqLite find
选择其中的ul
元素,并append
修改后的转换克隆:
html.find('ul').append(clone);
...最后用成品替换编译element
:
element.replaceWith(html);
你会找到一个有效的Plunker here。
答案 1 :(得分:0)
当我问这个问题时,我似乎并不完全理解任务。
但是当我看到@MarcKline的回答时,我对我的问题的有效性产生了怀疑,因为规则&#34; 如果你不能在没有角度的jQuery的情况下做到这一点,你可能做错了&#34;。
所以我改变了element
标签上的概念 - 现在它们也是容器,并且它们嵌套了html,并且也作为包装器工作。所以我的最终解决方案是:
angular.module('myApp', [])
.controller('MyController', function($scope){})
.directive('collection', function($compile){
return {
transclude: 'true',
restrict: 'E',
template: '<header>header</header><div><ul ng-transclude></ul></div><footer>footer</footer>',
}
})
.directive('element', function(){
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<li><div ng-transclude></div></li>'
}
});
<body ng-app="myApp" ng-controller="MyController">
<collection>
<element>inner1</element>
<element>inner2</element>
<element>inner3</element>
</collection>
</body>