【问题标题】:Angular ng-transclude scope in repeat重复的角度 ng-transclude 范围
【发布时间】:2016-07-12 07:36:33
【问题描述】:

我刚开始学习 AngularJS 并尝试使用多个插槽嵌入来实现自定义 table 指令。 并面临范围未转移到嵌入的情况。其他 StackOverflow 问题中有很多解决方案,但只有在指令模板 ng-repeat 出现在顶部元素中时,所有这些解决方案才有效,但我的情况并非如此。 至少我不能采用所有这些解决方案。

简化版。 指令:

<span>
  <div>Some pagination</div>
  <div style="display: inline"><input type="text" placeholder="Search"/></div>
  <div style="display: inline">Some filters</div>

  <table>
    <tbody>
      <tr ng-repeat="line in lines" ng-transclude="row">
      </tr>
    </tbody>
  </table>

  <div>Some pagination again</div>
</span>

指令的使用:

<my-table>
     <row>
          <td>{{line.col1}}</td>
          <td>{{line.col2}}</td>
      </row>
</my-table>

Plunkr 上脚本的完整示例: https://plnkr.co/edit/rg43ZdPMGHLBJCTLOoLC

非常感谢任何建议。

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    在嵌入模板中直接引用ng-repeat 创建的$scope 对象的最简单且可能最简洁的方法是通过$parent 属性:

    <my-table>
      <td>{{$parent.line.col1}}</td>
      <td>{{$parent.line.col2}}</td>
    </my-table>
    

    为嵌入模板创建的$scope$parent 属性指向最终嵌入该模板的目标模板的$scope(在本例中为ng-repeat),即使此类嵌入$scope 不是通常意义上的目标 $scope 的子对象,这是嵌入的结果。有关此问题的更完整讨论,请参阅 this wonderful blog post

    工作人员:https://plnkr.co/edit/LoqIMiQVZKlTt5epDnZF?p=preview.

    【讨论】:

    • 你知道为什么用 td 标签而不是 angular insert &lt;span class="ng-binding ng-scope"&gt; testCol1 testCol2 &lt;/span&gt; 吗?
    • 是的,它与浏览器在嵌入之前注册无效的 html 有关(据我所知)。这是一个与更普遍地嵌入&lt;td&gt; 元素有关的问题。查看stackoverflow.com/questions/26048996/… 了解可能的解决方法
    • 请注意,ng-bindingng-scope “类”只是普通的角度内部管理。我上面的评论是关于您看到的 元素强制
    【解决方案2】:

    您需要手动使用 $transclude 函数并为每一行创建新的子范围。除此之外,如果您使用隔离范围(并且您正在使用它),则需要将行传递给指令。 您的链接函数应如下所示:

    link: function($scope, $element, $attrs, controller, $transclude) {
          var tbody = $element.find('tbody');
    
          $scope.$watch('lines', function (lines) {
            tbody.empty();
    
            lines.forEach(function (line) {
              var childScope = $scope.$new();
              childScope.line = line;
    
              $transclude(childScope, function (content) {
                tbody.append('<tr>');
                tbody.append(content);
                tbody.append('</tr>');
              }, null,  'row');
            });
          });
        }
    

    Plunker:https://plnkr.co/edit/MLNZOmoQyMazgIpluMqO?p=preview

    但这无论如何都是个坏主意,因为这种方式很难创建表。如您所见,子元素不是元素。您必须做一些 DOM 操作才能使其工作。

    【讨论】:

    • 谢谢。有用。有没有办法获取确切元素的范围。在我的真实指令中,我有从外部 api 获取的附加值,它们不在最顶层指令范围内
    • 您能否再为这个解决方案提供一个提示 - 如何强制这个新添加的元素使用引导样式。它现在根本没有风格。
    【解决方案3】:

    我知道你真的不需要使用属性

    所以代码看起来更简单干净:

     <body ng-controller="tableCtrl">
       <h1>Table test</h1>
       <my-table lines="lines"></my-table>
     </body>
    

    你的模板:

        <span>
          <div>Some pagination</div>
          <div style="display: inline"><input type="text" placeholder="Search"/></div>
          <div style="display: inline">Some filters</div>
    
          <table>
            <tbody>
              <tr ng-repeat="line in lines">
                   <td>{{line.col1}}</td>
                   <td>{{line.col2}}</td>
              </tr>
            </tbody>
          </table>
    
          <div>Some pagination again</div>
        </span>
    

    和角度指令:

       angular.module('myApp', [])
        .directive("myTable", function() {
          return {
            restrict: 'E',
            transclude: true,
            scope: {
              lines:'=lines',
              api: '@'
            },
            templateUrl: "template.html",
          };
        })
        .controller("tableCtrl", ['$scope', function($scope) {
          $scope.lines = [
            {col1: "testCol1", col2: "testCol2"},
            {col1: "testCol11", col2: "testCol21"}
            ];
        }]);
    

    plunkr 中的工作示例:https://plnkr.co/edit/iMxRoD0N3sUXqmViHAQh?p=preview

    【讨论】:

    • 这个解决方案对我没有帮助,因为行数组实际上是由分页器获取并放置在元素的范围内,所以我没有它在指令之外。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 2016-01-22
    • 2014-10-29
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多