模板内指令内的指令不起作用

Directive within a directive within a template not working

我是一个 Angular 菜鸟。我将我的窗格构建为 table 的集合,并使用指令使模板 HTML 从 table 实现中抽象出来。窗格被正确嵌入,但内部只包含文本而不是 table 结构。这是我的代码:

<!DOCTYPE html>
<html>

<head>
<script src= "angular.js"></script>
<script src= "angular-sanitize.js"></script>
</head>

<body ng-app="pp">

<div ng-controller="ppMain">
  <ul class="menu">
    <li ng-repeat="pageID in homePageList">{{pages[pageID].str}}</li>
  </ul>
  <div>
    <div ng-repeat="pageID in pageList" ng-bind-html="pages[pageID].template">
    </div>
  </div>
</div>

<script>

var pp = {
    ctl: {}
};

pp.mod = angular.module('pp', ['ngSanitize']);
pp.mod.directive({
    'ppHeader': function () {
        return ({
        });
    },
    'ppGroup': function () {
        return ({
            template: '<table ng-transclude></table>',
            transclude: true,
            restrict: 'EA'
        });
    },
    'ppRow': function () {
        return ({
            template: '<tr ng-transclude></tr>',
            transclude: true,
            restrict: 'EA'
        });
    },
    'ppLabel': function () {
        return ({
            template: '<td ng-transclude></td>',
            transclude: true,
            restrict: 'EA'
        });
    },
    'ppValue': function () {
        return ({
            template: '<td ng-transclude></td>',
            transclude: true,
            restrict: 'EA'
        });
    },
});
pp.ctl.main = pp.mod.controller('ppMain', ['$scope', function ($scope) {
    $scope.curPage = 'page1';
    $scope.pages = {
        "page1": {
            str: "page 1",
            template:'\
                <pp-group>\
                    <pp-row>\
                        <pp-label>Page:</pp-label><pp-value>1</pp-value>\
                    </pp-row>\
                </pp-group>\
            '},
        "page2": {
            str: "page 2",
            template:'\
                <pp-group>\
                    <pp-row>\
                        <pp-label>Page:</pp-label><pp-value>2</pp-value>\
                    </pp-row>\
                </pp-group>\
            '},
        "page3": {
            str: "page 3",
            template:'\
                <pp-group>\
                    <pp-row>\
                        <pp-label>Page:</pp-label><pp-value>3</pp-value>\
                    </pp-row>\
                </pp-group>\
            '}
    };
    $scope.pageList = ["page1","page2","page3"];
    $scope.homePageList = ["page2", "page3"];

}]);


</script> 

</body>
</html>

使用调试器查看生成的 DOM,我发现没有 table,只有文本。

ng-bind-html 这是不可能的,因为 ng-sanitize 不编译 html。它只能用于静态内容。您需要为此自己创建一个指令。

像这样:

.directive('compileHtml', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, elm, attrs) {
      var template = scope.$eval(attrs.compileHtml); //get the template by evaluating
      elm.html(template); //set the html
      $compile(elm.contents())(scope); //compile the contents
    }
  }
});

还要记住,您有没有替换的子指令,这意味着您将创建无效的 html,由 ppGroup 创建的 table 将有 ppRow 作为子指令这会导致 html 无效,并且会将指令内容推出 table 并且编译将无法正常进行。因此,您需要在这些指令上使用选项 replace:true

但是,动态编译 html 确实不安全,除非您知道它来自受信任的来源,即 [=13= 使用的 $sce 服务] 做。它清理绑定html.

演示

var pp = {
  ctl: {}
};

pp.mod = angular.module('pp', ['ngSanitize']);

pp.mod.directive({
  'ppHeader': function() {
    return ({});
  },
  'ppGroup': function() {
    return ({
      template: '<table ng-transclude></table>',
      transclude: true,
      restrict: 'EA'
    });
  },
  'ppRow': function() {
    return ({
      replace: true,
      template: '<tr ng-transclude></tr>',
      transclude: true,
      restrict: 'EA'
    });
  },
  'ppLabel': function() {
    return ({
      replace: true,
      template: '<td ng-transclude></td>',
      transclude: true,
      restrict: 'EA'
    });
  },
  'ppValue': function() {
    return ({
      replace: true,
      template: '<td ng-transclude></td>',
      transclude: true,
      restrict: 'EA'
    });
  },
}).directive('compileHtml', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, elm, attrs) {
      var template = scope.$eval(attrs.compileHtml);
      elm.html(template);
      $compile(elm.contents())(scope);
    }
  }
});
pp.ctl.main = pp.mod.controller('ppMain', ['$scope',
  function($scope) {
    $scope.curPage = 'page1';
    $scope.pages = {
      "page1": {
        str: "page 1",
        template: '\
                <pp-group>\
                    <pp-row>\
                        <pp-label>Page:</pp-label><pp-value>1</pp-value>\
                    </pp-row>\
                </pp-group>\
            '
      },
      "page2": {
        str: "page 2",
        template: '\
                <pp-group>\
                    <pp-row>\
                        <pp-label>Page:</pp-label><pp-value>2</pp-value>\
                    </pp-row>\
                </pp-group>\
            '
      },
      "page3": {
        str: "page 3",
        template: '\
                <pp-group>\
                    <pp-row>\
                        <pp-label>Page:</pp-label><pp-value>3</pp-value>\
                    </pp-row>\
                </pp-group>\
            '
      }
    };
    $scope.pageList = ["page1", "page2", "page3"];
    $scope.homePageList = ["page2", "page3"];

  }
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular-sanitize.min.js"></script>
<div ng-app="pp">

  <div ng-controller="ppMain">
    <ul class="menu">
      <li ng-repeat="pageID in homePageList">{{pages[pageID].str}}</li>
    </ul>
    <div>
      <div ng-repeat="pageID in pageList" compile-html="pages[pageID].template">
      </div>
    </div>
  </div>
</div>