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

Wrapping template of element directive in collection directive

本文关键字:指令 元素 包装 集合      更新时间:2023-09-26

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

<collection>
    <element/>
    <element/>
</collection>

他们有模板:

collection.html

<header>header</header>
<div><ul>...</ul></div>
<footer>footer</footer>

element.html

<p>element</p>

应该用什么代替collection.html中的...来用<li>..</li>包裹每个element

表达结果

<header>header</header>
<div>
  <ul>
    <li><p>element</p></li>
    <li><p>element</p></li>
  </ul>
</div>
<footer>footer</footer>

更新

在回顾问题背后的任务时,似乎element标记实际上是嵌套HTML的包装器,这简化了事情。因此,我添加了一个答案,描述了如何使用2级嵌套transclusion。

ng-transclude允许您在模板化指令中嵌套内容,这样您就可以在指令编译阶段操作transcluded元素。

在这种情况下,您需要使用transclude: 'element'来跨接整个collection元素。这是因为您需要以结构化的方式对子元素进行操作(使用transclude: true提供了所有子节点的平面阵列,而这在这里不起作用(。

.directive('collection', function(){
      return {
        transclude: 'element',

使用transclusion时,指令的编译函数中会有一个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);

最后用成品代替编译后的CCD_ 19

element.replaceWith(html);

你会在这里找到一个工作的Plunker。

当我问这个问题时,我似乎没有完全理解任务。

但当我看到@MarcKline的回答时,我对我的问题的有效性产生了怀疑,因为规则">如果你不能在没有角度jQuery的情况下完成它,你可能做错了"。

因此,我改变了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