在集合指令中包装元素指令的模板

时间:2014-05-14 13:22:45

标签: javascript angularjs angularjs-directive angularjs-ng-repeat

我有两个元素指令collectionelement,应该像这样使用:

<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级嵌套转换。

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){

要开始操作我们将添加的内容,请迭代克隆的子元素,使用jqLit​​e wrap函数将它们与列表项标签包装在一起:

angular.forEach(clone.children(), function(el){
  var el = angular.element(el);
  el.replaceWith(el.wrap('<li></li>'));
});

然后从存储在传递给compile / link的元素中的HTML中创建并存储一个新的jqLit​​e元素:

var html = angular.element(element.html());

使用jqLit​​e 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>

plunkr