Использование ng-transclude, похоже, не работает хорошо в таблице

Я создал простую директиву, которая используется для отображения некоторого текста в <td>, когда нет данных таблицы (т.е. "Не найдено результатов" ) занимает всю строку таблицы. До того, как я просто разместил статический текст в <td>, но теперь я хочу, чтобы в него был добавлен любой DOM. Я попытался добавить ng-transclude в свою директиву, но теперь это странный способ визуализации элемента.

Вот моя директива:

app.directive('skNoResult', ['$rootScope', function () {
    return {
        restrict: 'A',
        replace: true,
        transclude: true,
        template: '<tr ng-if="!hasResult"><td class="left" colspan="{{ colSpan }}"><ng-transclude></ng-transclude></td></tr>',
        link: function (scope, elem, attrs, ctrl) {
            var span = angular.element(elem).parents('tbody').siblings('thead').find('tr').children().length;

            scope.colSpan = span;

            scope.$watch(attrs.skNoResult, function (list) {
                if (list.length) {
                    scope.hasResult = true;
                } else {
                    scope.hasResult = false;
                }
            });
        }
    };
}]);

В основном он просто отслеживает набор данных (массив) и проверяет длину, чтобы увидеть, есть ли какие-либо данные или нет. Если есть, то мы выводим эту строку с помощью ngIf.

Мой html просто выглядит как

<tr sk-no-result="model.dataSet">Here is my text I want to transclude into my directive</tr>

Проблема заключается в том, что переведенный текст вставляется в DOM как только текстовыйNode и появляется выше <table>, а не внутри него. Любая идея, почему это происходит?

Ответ 1

Я считаю, что причина, по которой вы это видите, связана не с Angular, а с браузером, который видит недопустимый html внутри <tr>, поскольку он ожидает <td>, и в результате он перемещает это содержимое выше таблица ДО Angular даже получает возможность запускать и выполнять переход. Вы можете легко проверить это, удалив любой код Angular и просто оставьте HTML, и вы заметите, что результат точно такой же.

Ниже приведено обходное решение, которое вы можете использовать:

<tr ng-if="!model.dataSet.length">
  <td sk-no-result="model.dataSet">Here is my text I want to transclude into my directive</td>
</tr>

И директива:

app.directive('skNoResult', ['$rootScope', function () {
  return {
    restrict: 'A',
    replace: true,
    transclude: true,
    template: '<td class="left" colspan="{{ colSpan }}"><div ng-transclude></div></td>',
    link: function (scope, elem, attrs) {
        var span = angular.element(elem).parents('tbody').siblings('thead').find('tr').children().length;
        scope.colSpan = span;
    }
  };
}])

Обратите внимание, что использование элемента ngTransclude, т.е. <ng-transclude></ng-transclude>, доступно только из Angular версии 1.3.0-beta.16 и выше. Если вы используете выпуск 1.2, вам нужно использовать использование атрибута, как в приведенном выше примере <div ng-transclude></div>

Вот рабочая демонстрация .