AngularJS:"指令模板必须只有一个根元素",当在指令模板中使用"th"标签时



我正在尝试实现自定义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标签时,一切正常。

我做错了什么?

我遇到了像指令和表元素这样的奇怪之处。例如,请参阅此问题。尝试使用div标签包装模板或使用replace:false.

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

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

我摆脱了评论,瞧 - 问题解决了。

我希望在<tr>上下文之外评估<th>在某个中间点被融化(将该模板放入网页的某个随机部分以查看<th>消失)。

在您的位置上,我会在模板中使用<div>,将sort-by-directive更改为"A"类型指令,并像以前一样使用<th sort-by-directive>...</th>而不replace: true.

此错误也可能是由于您需要在指令模板中的所有标签都有一个包装元素而导致的。指令的模板不能仅包含:

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

它必须是:

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

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

我知道这很老,但还有另一种解决方案。 我也遇到了这个问题,并尝试了上述所有解决方案,但没有运气。

事实证明,出于某种奇怪的原因,如果"templateUrl"中有拼写错误,也会抛出此错误 - 如果 angular 无法通过给定路径找到 html 文件 - 你会得到同样的"必须只有一个根元素"错误。

所以 - 修复模板网址为我修复了错误。

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

正如其他人所说:这是因为您的浏览器在将 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>

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

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

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

Aaron 答案的一个更具体的情况是,当你认为你有正确的模板路径,而实际上你没有:正如templateUrl文档中所述

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

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

我遇到以下错误:

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

我通过删除模板文件顶部的逗号来绕过。

替换为 AngularJS 1.3 向前,下一个版本将完全删除它,最好不要使用 replace 键。

你使用的是哪个版本的 angular?

有一个看起来像您的问题的错误,已在1.2.13 1.3Beta 1 提交链接中修复

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

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

以前:

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

后:

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

补充 Biljana 的答案,当你认为你有正确的模板路径而实际上没有,特别是 dos/mac/unix 系统中的大写/小写差异。

我的本地路径:

模板网址: 'ng/ImageDnd/dropzone.tpl.html',

我真正的道路:

ng/ImageDnD/dropzone.tpl.html

请注意注释 Dnd 末尾的 D。

我的Macbook没有抱怨,但在Linux中部署时遇到了错误。

最新更新