Подтвердить что ты не робот

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 на a или span все работает нормально.

Что я делаю неправильно?

4b9b3361

Ответ 1

Я ожидаю, что <th> будет расплавлен в некоторой промежуточной точке, когда он оценивается вне контекста <tr> (поместите этот шаблон в какую-нибудь случайную часть вашей веб-страницы, чтобы исчезнуть <th>).

В вашей позиции я использовал бы <div> в шаблоне, изменил бы sort-by-directive на директиву типа "A" и использовал бы <th sort-by-directive>...</th>, как и раньше, без replace: true.

Ответ 2

Я встречал такие странности, как элементы директивы и таблицы. См. issue, например. Попробуйте обернуть ваш шаблон тегом div или используйте replace:false.

Ответ 3

Это не ваше дело, но у меня была такая же проблема, потому что у моего кода были комментарии html до и после разметки шаблона, например:

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

Я избавился от комментариев и вуаля - проблема решена.

Ответ 4

Эта ошибка также может быть вызвана тем фактом, что в шаблоне директивы вам необходимо иметь элемент упаковки для всех ваших тегов. Шаблон вашей директивы не может быть только:

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

Это должно быть:

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

Ответ 5

Я получил эту ошибку, когда использовал свойство template определения директивы, когда я должен был использовать templateUrl, если это кому-то помогает.

Ответ 6

Как заявлено другими: это потому, что ваш браузер игнорирует 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>

Ответ 7

i возникает следующая ошибка:

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

Я обойду, удалив commement в самом верху файла шаблона.

replace устаревает с угловым 1.3 вперёд, следующий релиз полностью удалит его, лучше не использовать ключ замены.

Ответ 8

Я столкнулся с проблемой пару раз, и в большинстве случаев это может быть то, что вы не обертываете свои элементы под одним элементом, например

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

Но был один случай, когда вы получаете эту ошибку, когда путь к шаблону неверен. Поэтому, пожалуйста, проверьте правильность ссылок на шаблон.

Ответ 9

Какую версию angular вы используете?

Была ошибка для чего-то похожего на вашу проблему, которая была исправлена ​​в 1.2.13 1.3 Beta 1 commit link

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

Ответ 10

Я знаю, что это старо, но есть другое решение. Я тоже столкнулся с этой проблемой и не поверил всем этим решениям.

получается, по какой-то странной причине, что эта ошибка возникает и в случае, если в "templateUrl" есть опечатка - если angular не может найти файл html по данному пути - вы получите то же самое ", должен иметь ровно одну ошибку корневого элемента.

так что исправление templateUrl исправило ошибку для меня.

надеюсь, что это поможет любому в будущем.