AngularJS ng-repeat 与表格内的自定义元素呈现奇怪

Posted

技术标签:

【中文标题】AngularJS ng-repeat 与表格内的自定义元素呈现奇怪【英文标题】:AngularJS ng-repeat with custom element inside a table is rendering strangely 【发布时间】:2013-09-07 04:27:09 【问题描述】:

我正在尝试在多个地方重复使用我的 html 视图的一部分。我要重复使用的部分是 HTML 表格中的表格单元格。问题是我在 ng-repeat 中的自定义指令正在做一些有趣的事情。我已经在jsFiddle 上重现了这个问题。 jsFiddle 中有两个 HTML 表。第一个是 ng-repeat,表格单元格写入视图,第二个是来自指令 my-element 的表格单元格。 Chrome 开发工具报告呈现的 HTML 看起来像这样。请注意,自定义元素只出现一次并且位于表格之外。

渲染的 HTML

<div ng-controller="MyCtrl" class="ng-scope">
    table1
    <table class="table table-hover">
      <tbody><!-- ngRepeat: p in people -->
          <tr ng-repeat="p in people" class="ng-scope">
            <td class="ng-binding">Name: Mike</td>
            <td class="ng-binding">Age: 20</td>
          </tr>
          <tr ng-repeat="p in people" class="ng-scope">
            <td class="ng-binding">Name: Peter S</td>
            <td class="ng-binding">Age: 22</td>
          </tr>
      </tbody>
    </table>
    <br>table2
    <my-element class="ng-binding">Name: Age: </my-element>
    <table class="table table-hover">
      <tbody>
        <!-- ngRepeat: p in people -->
        <tr ng-repeat="p in people" class="ng-scope">
        </tr>
        <tr ng-repeat="p in people" class="ng-scope">    
        </tr>
      </tbody>
    </table>
</div>

源 HTML

<div ng-controller="MyCtrl">
    table1
    <table class="table table-hover">
        <tr ng-repeat="p in people">
            <td>Name:  p.name </td>
            <td>Age:  p.age </td>
        </tr>
    </table>
    <br/>table2
    <table class="table table-hover">
        <tr ng-repeat="p in people">
            <my-element></my-element>
        </tr>
    </table>
</div>

源代码

var app = angular.module('myApp', []);

app.directive('myElement', function () 
    return 
        restrict: 'E',
        template: '<td>Name:  p.name </td><td>Age:  p.age </td>'
    
);

function MyCtrl($scope) 
    $scope.people = [
        name: 'Mike',
        age: 20
    , 
        name: 'Peter S',
        age: 22
    ];

请注意 jsFiddle 是一个微不足道的例子,常识会导致根本不使用指令。但是,我的目标代码有一个更大的模板,我想重用它。我也尝试过使用“ng-include”,但结果相似。

【问题讨论】:

发生这种情况的原因是“采用代理算法”,它是您浏览器的一部分。在检查 DOM 时,my-element 被移到 table 元素之外,因为需要一个 tr 元素。 【参考方案1】:

&lt;td&gt; 已知在这样的指令中表现异常。相反,在父 &lt;tr&gt; 上使用指令。在此处阅读有关此问题的更多信息:https://github.com/angular/angular.js/issues/1459

<table>
    <tr ng-repeat="p in people" my-element></tr>
</table>

您可以通过以下方式进一步改进指令,使其更易于重复使用。

app.directive('myElement', function () 
  return 
    scope: 
      item: '=myElement'
    ,
    restrict: 'EA',
    template: '<td>Name: item.name</td><td>Age: item.age</td>'
    ;
);

并像这样传递item 的值:

  <table>
    <tr ng-repeat="person in people" my-element="person"></tr>
  </table>

Live Demo

【讨论】:

m59 和 @sza 的答案都有效,但我很欣赏关于代码改进的额外 cmets。 那么这个解决方案有什么特别之处呢? 抱歉。命名使您的意图不清楚。我以为你在做别的事情。 这可行,但呈现的 html 会丢失内部 td 标签。例如姓名:MikeAge:20,Mike 和 Age 之间没有任何关系。知道为什么吗? @ChrisHayes 当然,将它传递给范围。 index="$index"scope: index: '=', 【参考方案2】:

像这样将指令应用于&lt;tr&gt;

<table class="table table-hover">
    <tr my-element blah='p' ng-repeat="p in people"></tr>
</table>

app.directive('myElement', function () 
    return 
        restrict: 'A',
        scope:
            ngModel: '=blah'
        ,
        template: '<td>Name:  ngModel.name </td><td>Age:  ngModel.age </td>'
    
);

Working Demo

【讨论】:

我会避免这种情况 - 重复使用 ng-model 似乎不必要地将事情与正常使用 ng-model 和与表单绑定等混淆。 @TheBigC 我想我最好将其重命名为其他名称。谢谢。 @TheBigC 这个根本不重要。【参考方案3】:

在您的指令中使用replace: true,您的&lt;my-element&gt; 将替换为模板中的根项目&lt;td&gt;,因此这不会混淆HTML。

【讨论】:

对于当前模板,这将导致 模板必须只有一个根元素。 错误。 啊,当然可以。如果在 的上下文中有效,则可能包含在 &lt;tbody&gt; 中。否则请参阅 m59 的答案。 好主意,但无论如何似乎都会抛出该模板错误。不知道如何解决。

以上是关于AngularJS ng-repeat 与表格内的自定义元素呈现奇怪的主要内容,如果未能解决你的问题,请参考以下文章

Angularjs 表排序与 ng-repeat

AngularJS NG-repeat:如何重复必须过滤唯一值的ng-repeat内的数据

angularJs ng-repeat并显示表格上方的错误

AngularJS的ng-repeat显示表格

使用Angular JS时如何在ng-repeat内的img标签中显示图像?

AngularJS 表格