在指令中包装md-tabs会产生“Orphan ngTransclude Directive”错误

时间:2016-06-30 15:37:21

标签: angularjs angularjs-directive angularjs-scope angular-material angularjs-ng-transclude

我想创建一个包装md-tabs的指令,但是我收到一个错误,“Orphan ngTransclude Directive”。我已在此代码段中复制了错误:

angular.module('transcludeExample', ['ngMaterial'])
   .directive('worksGreat', function(){
      return {
        restrict: 'E',
        transclude: true,
        template: '<ng-transclude></ng-transclude>'
      };
  })
  .directive('doesntWork', function(){
      return {
        restrict: 'E',
        transclude: true,
        template: '' + 
         '<md-tabs md-dynamic-height>' +
           '<md-tab label=\'tab 1\'>' + 
             '<ng-transclude></ng-transclude>' +
           '</md-tab>' +
         '</md-tabs>'
      };
  })
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example - example-simpleTranscludeExample-production</title>
  
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.2/angular-material.min.css">
</head>
<body ng-app="transcludeExample">
  <!-- Angular Material Dependencies -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>

    <!-- Angular Material Javascript using GitCDN to load directly from `bower-material/master` -->
    <script src="https://gitcdn.link/repo/angular/bower-material/master/angular-material.js"></script>

<div>
  <h3>ng-transclude in a directive works great:</h3>
  <works-great>Inner text</works-great>
  <hr/>
  
  <h3>md-tabs without a directive works great:</h3>
  <md-tabs md-dynamic-height>
    <md-tab label="tab 1">
      Inner text
    </md-tab>
  </md-tabs>
  <hr/>
  
  <h3>combining md-tabs with a directive doesn't work:</h3>
  <doesnt-work>Inner text</doesnt-work>
</div>
</body>
</html>

我发现this answer可以手动操作模板外部的元素,但我希望有一种更清晰的“更有棱角”的方式。这里发生了什么?有没有办法可以定义ng-transclude应该适用的指令?

1 个答案:

答案 0 :(得分:0)

This comment on github提出了解决方案。 ng-transclude被设计为通用的,因此它可以与任何指令一起使用,但在这种情况下,这就是问题的来源。幸运的是,模仿非常简单,我们可以使用require指定应该应用哪个父项。

我已使用有效的解决方案更新了我的代码段:

var orphanDemoCtrl = function($transclude){
  this.$transclude = $transclude;
}

angular.module('transcludeExample', ['ngMaterial'])
  .controller('orphanDemoCtrl', orphanDemoCtrl)
  .directive('orphanDemo', function(){
      return {
        restrict: 'E',
        transclude: true,
        template: '' + 
         '<md-tabs md-dynamic-height>' +
           '<md-tab label=\'tab 1\'>' + 
             '<orphan-demo-transclude></orphan-demo-transclude>' +
           '</md-tab>' +
         '</md-tabs>',
        controller: orphanDemoCtrl
      };
  })
  .directive('orphanDemoTransclude', function(){
      return {
        require: "^orphanDemo",
        link: function($scope, $element, $attrs, orphanDemoCtrl){
          orphanDemoCtrl.$transclude(function(clone) {
            $element.empty();
            $element.append(clone);
          });
        }
     }
  })
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Example - example-simpleTranscludeExample-production</title>
  
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/0.11.2/angular-material.min.css">
</head>
<body ng-app="transcludeExample">
  <!-- Angular Material Dependencies -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-animate.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-aria.js"></script>

    <!-- Angular Material Javascript using GitCDN to load directly from `bower-material/master` -->
    <script src="https://gitcdn.link/repo/angular/bower-material/master/angular-material.js"></script>

<div>  
  <h3>combining md-tabs with a directive works now:</h3>
  <orphan-demo>Inner text</orphan-demo>
</div>
</body>
</html>