AngularJS:指令中 templateUrl 的奇怪行为(模板运行良好)

AngularJS: strange behavior on templateUrl in directive(template works well)

我有两个指令,一个是table,一个是按钮。
但是当我在按钮指令中使用 templateUrl 时,所有按钮都显示在 table 中的同一行中。
但是 "template" 可以很好地工作。
有人可以帮忙吗?

这两个demo的插件如下:
http://plnkr.co/edit/9EaRfrSQggPETrXhNZvq?p=preview : 使用 templateUrl
http://plnkr.co/edit/UHzEpugxtM6JjoNrUd9X?p=preview : 使用模板

指令 myButton1 和 myButton2 之间的唯一区别是:
myButton1 使用:
templateUrl: 函数(元素,属性){
return TEMPLATE_ACTION;
}
"actionTemplate.html"的内容为:

<div ng-if="config !== undefined">b</div><br/><br/>

myButton2 使用:
模板: '<div ng-if="config !== undefined">b</div>',

    angular.module('myApp', [])
            .controller('MyController', ['$scope', function ($scope) {
                $scope.data = [
                    {name: 'field1', config: {type: 'config1'}},
                    {name: 'field2', config: {type: 'config2'}}
                ];
            }])
            .directive('myGrid', ['$compile', function($compile) {
                return {
                    restrict: 'E',
                    replace: true,
                    template: '' +
                        '<table>' +
                        '<tbody>' +
                        '<tr ng-repeat="item in data">' +
                        '    <td><div><my-button2 config="item.config"></my-button2></div></td>' +
                        '    <td>{{item.name}}</td>' +
                        '</tr>' +
                        '</tbody>' +
                        '</table>',
                    scope: true
                }
                }])
            .directive("myButton1", ["$compile",
                function ($compilee) {
                    var TEMPLATE_ACTION = 'views/actionTemplate.html';
                    return {
                        restrict: "E",
                        replace: true,
                        scope: true,
                        templateUrl: function (element, attrs) {
                            return TEMPLATE_ACTION;
                        },
                        link: function (scope, iElement, iAttrs) {
                            var config = scope.$eval(iAttrs.config);
                            scope.config = config;
                        }
                    };
                }
            ])
    ;

结果是两个按钮显示在同一行如下:

但是在指令中使用"template",效果很好:

        angular.module('myApp', [])
            .controller('MyController', ['$scope', function ($scope) {
                $scope.data = [
                    {name: 'field1', config: {type: 'config1'}},
                    {name: 'field2', config: {type: 'config2'}}
                ];
            }])
            .directive('myGrid', ['$compile', function($compile) {
                return {
                    restrict: 'E',
                    replace: true,
                    template: '' +
                        '<table>' +
                        '<tbody>' +
                        '<tr ng-repeat="item in data">' +
                        '    <td><div><my-button2 config="item.config"></my-button2></div></td>' +
                        '    <td>{{item.name}}</td>' +
                        '</tr>' +
                        '</tbody>' +
                        '</table>',
                    scope: true
                }
                }])
            .directive("myButton2", ["$compile",
                function ($compilee) {
                    return {
                        restrict: "E",
                        replace: true,
                        scope: true,
                        template: '<div ng-if="config !== undefined">b</div>',
                        link: function (scope, iElement, iAttrs) {
                            var config = scope.$eval(iAttrs.config);
                            scope.config = config;
                        }
                    };
                }
            ])
    ;

结果如下:

同时使用 ng-repeattemplateUrlng-ifreplace:true 时可能会出现已知问题,尽管据说已多次修复。

可能是 angular 中的 transclude 逻辑有问题。

ng-ifng-repeat是angular中的两个特殊指令,同时templateUrl中的DOM是异步加载的,挂起汇编。这种复杂的情况会以某种方式产生问题。

为避免这种情况,只需使用 ng-show 代替 ng-if,或 template 代替 templateUrl,或为 templateUrl 设置脚本模板以将其放入$templateCache.

已知问题参考(或者您可以 google 更多自己的)

https://github.com/angular/angular.js/issues/14326 https://github.com/angular/angular.js/issues/11855 https://github.com/angular/angular.js/issues/7183