我创建了一个简单的指令,该指令用于在没有表数据(即“未找到结果”)占用表的整个行时在<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>

问题在于,被嵌入的文本仅作为textNode插入到DOM中,并出现在<table>的上方而不是其内部。知道为什么会这样吗?

最佳答案

我相信您看到它的原因不是因为Angular,而是浏览器看到它在<tr>中是无效的html,因为它期望<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;
    }
  };
}])

请注意,只有Angular版本1.3.0-beta.16和更高版本才能使用ngTransclude的元素用法,即<ng-transclude></ng-transclude>。如果您使用的是1.2版本,则需要使用属性用法,如上面的示例<div ng-transclude></div>
这是一个有效的demo

10-06 00:15