【问题标题】:AngularJS: 'Template for directive must have exactly one root element' when using 'th' tag in directive templateAngularJS:在指令模板中使用“th”标签时,“指令模板必须只有一个根元素”
【发布时间】:2014-04-17 21:26:48
【问题描述】:

我正在尝试实现自定义 sortBy 指令,以使 html 表中的列可排序。

HTML:

<thead>
   <tr>
    <sort-by-directive
      ng-repeat="header in headers"
      onsort="onSort"
      sortdir="filterCriteria.sortDir"
      sortedby="filterCriteria.sortedBy"
      sortvalue="{{ header.value }}">{{ header.title }}
    </sort-by-directive>
  </tr>
</thead>

JS:

angular.module('mainApp.directives').directive('sortByDirective', function () {

        return {
            templateUrl: 'SortHeaderTemplate',
            restrict: 'E',
            transclude: true,
            replace: true,
            scope: {
                sortdir: '=',
                sortedby: '=',
                sortvalue: '@',
                onsort: '='
            },
            link: function (scope, element, attrs) {
                scope.sort = function () {
                    if (scope.sortedby == scope.sortvalue)
                        scope.sortdir = scope.sortdir == 'asc' ? 'desc' : 'asc';
                    else {
                        scope.sortedby = scope.sortvalue;
                        scope.sortdir = 'asc';
                    }
                    scope.onsort(scope.sortedby, scope.sortdir);
                }
            }
        };
    });

指令模板:

<script id="SortHeaderTemplate" type="text/ng-template">
<th ng-click="sort(sortvalue)">
  <span ng-transclude=""></span>
  <span ng-show="sortedby == sortvalue">
    <i ng-class="{true: 'sorting_asc', false: 'sorting_desc'}[sortdir == 'asc']"></i>
  </span>
  <span ng-show="sortedby != sortvalue">
    <i ng-class="{true: 'sorting', false: 'sorting'}[sortdir == 'asc']"></i>
  </span>
</th>
</script>

所以当我使用th 作为指令模板的根标记时,我检索到一个错误:

Error: [$compile:tplrt] Template for directive 'sortByDirective' must have exactly one root element. SortHeaderTemplate

但是当我将th 更改为aspan 标签时,一切正常。

我做错了什么?

【问题讨论】:

    标签: javascript angularjs angularjs-directive


    【解决方案1】:

    我在指令和表格元素中遇到过类似的怪事。例如,请参阅此issue。尝试使用div 标记或使用replace:false 包装您的模板。

    【讨论】:

    • Diddo -- replace: true 对我来说很糟糕。
    • +1,将replace: true 更改为replace: false 对我有用,我的html 中甚至没有任何th tr td 元素
    • 为我工作,将其用作带有如下链接的菜单:&lt;li&gt;&lt;a href ng-click="redirectTodiv('mentionList', $event)"&gt;&lt;img title="Mentions List" src="images/postList.svg" title="" height="25" /&gt;&lt;span class="navText"&gt;Mentions List&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
    【解决方案2】:

    这不是你的情况,但我遇到了同样的问题,因为我的代码在模板标记之前和之后都有 html cmets,如下所示:

    <!-- Foo Widget -->
    <div class="foo-widget">[...]</div>
    <!-- end:: Foo Widget -->
    

    我摆脱了 cmets 并且瞧 - 问题解决了。

    【讨论】:

    • 是的,这也是我的问题。谢谢!
    • 这是我遇到过的最疯狂的 Angular 问题之一。非常感谢!
    【解决方案3】:

    我希望&lt;th&gt;&lt;tr&gt; 的上下文之外进行评估时会在某个中间点消失(将该模板放入网页的某个随机部分以查看&lt;th&gt; 消失)。

    在你的位置上,我会在模板中使用&lt;div&gt;,将sort-by-directive 更改为“A”类型指令,并像以前一样使用&lt;th sort-by-directive&gt;...&lt;/th&gt;没有replace: true .

    【讨论】:

    • replace: false为我醒来
    • 我们可以让它使用 replace :true 并限制类型 E
    【解决方案4】:

    这个错误也可能是由于您需要在指令模板中为所有标签提供一个包装元素。你的指令模板不能只是:

    <nav></nav>
    <div></div>
    

    一定是:

    <div>
     <nav></nav>
     <div></div>
    </div>
    

    【讨论】:

    • 在我的模板中添加包装元素为我解决了这个问题。感谢您的提示;0
    【解决方案5】:

    我在使用指令定义的template 属性时遇到了这个错误,而我应该一直使用templateUrl,如果这对任何人都有帮助的话。

    【讨论】:

      【解决方案6】:

      我知道这是旧的,但还有另一种解决方案。 我也遇到了这个问题,并尝试了上述所有解决方案,但没有成功。

      结果,出于某种奇怪的原因,如果“templateUrl”中有错字,也会引发此错误 - 如果 angular 无法通过给定路径找到 html 文件 - 你会得到相同的“必须有”恰好是一个根元素的错误。

      所以 - 修复 templateUrl 为我修复了错误。

      希望这对将来的任何人都有帮助。

      【讨论】:

        【解决方案7】:

        正如其他人所说:这是因为您的浏览器在将 TH 放入表中之前会忽略它。解决此问题的首选方法是将指令更改为属性指令并将其添加到表中的 TH 中。

        指令如下所示:

        .directive('sortByDirective', function () {
        
            return {
                templateUrl: 'SortHeaderTemplate',
                restrict: 'A',
                transclude: true,
                replace: false,
                scope: {
                    sortdir: '=',
                    sortedby: '=',
                    sortvalue: '@',
                    onsort: '='
                },
                link: function (scope, element, attrs) {
                    scope.sort = function () {
                        if (scope.sortedby == scope.sortvalue)
                            scope.sortdir = scope.sortdir == 'asc' ? 'desc' : 'asc';
                        else {
                            scope.sortedby = scope.sortvalue;
                            scope.sortdir = 'asc';
                        }
                        scope.onsort(scope.sortedby, scope.sortdir);
                    }
                }
            };
        });
        

        在您的页面上设置如下所示:

        <th sort-by-directive
          ng-repeat="header in headers"
          onsort="onSort"
          sortdir="filterCriteria.sortDir"
          sortedby="filterCriteria.sortedBy"
          sortvalue="{{ header.value }}">{{ header.title }}
        </th>
        

        【讨论】:

          【解决方案8】:

          我已经多次遇到这个问题,而且大多数时候可能是您没有将元素包装在一个元素下,例如

          <div>
            <div... </div>
          </div>
          

          但有一次当模板路径不正确时,您会收到此错误。因此,请检查您是否正确引用了模板。

          【讨论】:

            【解决方案9】:

            Aaron's answer 的一个更具体的情况是,当您认为您有正确的模板路径而实际上却没有:正如 documentation 中针对 @987654323 所述@

            URL 是相对于我们的index.html 文件

            就我而言,我将模板目录放在index.html 的下一级。当我将我的属性设置为templateUrl: '../templates/some-form.html' 时,路径是相对于脚本而不是相对于index.html,导致同样的错误。

            【讨论】:

              【解决方案10】:

              我遇到以下错误:

              Error: [$compile:tplrt] http://errors.angularjs.org/1.2.6/$compile/tplrt?p0=stockWidget&p1=stock.html.
              

              我通过删除模板文件顶部的评论来解决问题。

              在 angularjs 1.3 之前不推荐使用替换,下一个版本将完全删除它,最好不要使用替换键。

              【讨论】:

                【解决方案11】:

                您使用的是哪个版本的 Angular?

                1.2.13 1.3 Beta 1 commit link

                中修复了一个看起来像您的问题的错误

                https://github.com/angular/angular.js/issues/1459

                【讨论】:

                  【解决方案12】:

                  我知道这是非常古老的答案和问题,但我遇到了这个错误,并通过将我的评论放在 div 标签中来修复它。

                  之前:

                      <!--You commented code-->
                        <div>
                  
                        </div>
                  

                  之后:

                  <div>
                      <!--You commented code-->
                  </div>
                  

                  【讨论】:

                    【解决方案13】:

                    添加到 Biljana 的答案中,当您认为自己有正确的模板路径而实际上却没有时,特别是 dos/mac/unix 系统中的大写/小写差异。

                    我的本​​地路径:

                    templateUrl: 'ng/ImageDnd/dropzone.tpl.html',

                    我的真实路径:

                    ng/ImageDnD/dropzone.tpl.html

                    注意 AnnotationsDnd 末尾的 D。

                    我的 Macbook 没有报错,但在 Linux 中部署时出错。

                    【讨论】:

                      猜你喜欢
                      • 2015-03-15
                      • 1970-01-01
                      • 2017-08-09
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-02-02
                      • 2018-09-09
                      • 2016-09-07
                      • 2017-03-03
                      相关资源
                      最近更新 更多