Angular.js指令转换ngRepeat - 错误

时间:2013-11-21 18:27:58

标签: javascript angularjs

我正在尝试创建图表指令(对现有解决方案不感兴趣)。我希望使用bartemplate的子指令为每个条形图定义模板。我想迭代bartemplate,所以我想使用ng-repeatng-transclude的模板可以做到这一点......而角度则会产生错误。

Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found. Element: <div ng-repeat="bar in bars track by $index" ng-transclude="" class="ng-scope">

http://jsfiddle.net/jt4Y2/7/

所以你可能会问,为什么要换?我希望能够包含我添加到图表中的任何元素(即标签),而不会干扰<bartemplate>

1 个答案:

答案 0 :(得分:6)

您的代码有几个问题。首先,您通过在转换中进行转换来进行转换,从而使其复杂化。其次,你正在组合已经进行了转换的指令,例如ng-repeat和试图在其中转换,这是不行的。

我提供了您所需代码的简化版本:

http://jsfiddle.net/jt4Y2/6/

让我试着解释它在做什么。首先,我们有barchart指令。我冒昧地简化了,但只是让整个身体充当了一个酒吧的模板而不是bar-template指令。

因为我们设置了transclude: truebarchart div中的实际内容被从dom中删除,但是可以通过transclude函数使用,您可以通过该函数注入控制器$transclude参数。我们使用此功能并将其保存在我们的控制器上,以便我们稍后可以访问它。

然后,barchart指令被此模板替换:

<div xmlns="http://www.w3.org/2000/svg">
    <div ng-repeat="bar in bars track by $index" render-bar></div>
 </div>

请注意,没有ng-transclude。相反,我们创建自己的指令render-bar来渲染模板(这避免了与ng-repeat和它自己的转换的任何冲突)。

renderBar指令非常简单:

directive('renderBar', function(){
    return {
      require: '^barchart',
      link: function(scope, element, attrs, controller){
        controller.renderBarTemplate(scope, function(dom){              
          element.append(dom);
        });
      }
  }
});

首先,我们要求有一个父barchart指令。在link函数中,我们可以获取其控制器并访问存储的transclude函数,我们将其命名为renderBarTemplate

我们传递的第一个参数是范围,它使函数链接到当前范围(基本上是ng-repeat提供的范围,它允许我们访问包括bar的迭代变量。

编译后的dom通过回调(第二个参数)返回,我们可以将其附加到<div>提供的ng-repeat

如果您有任何疑问或需要进一步澄清,请与我们联系。

<强>更新

这是一个允许你保留<bartemplate>指令的版本:

http://jsfiddle.net/jt4Y2/10/

我添加了bartemplate指令:

directive('bartemplate', function(){
  return {
    transclude: true,
    restrict: 'E',
    require: '^barchart',
    link: function(scope, element, attrs, barChartController, transclude){
        element.remove();
        barChartController.renderBarTemplate=transclude;
    } 
  };
})

它现在负责获取其transclude功能并将其存储在父控制器中。 (因此稍后可以使用render-bar指令。

另请注意element.remove()。这不是绝对必要的,只是从html中删除了重新<bartemplate>标记。