Lune
Lune

Reputation: 351

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

I have two directives, one is table, the other one is button.
But when I use templateUrl in button directive, all buttons are displayed in the same line in table.
But "template" can work well.
Anyone can help on this?

The plunker of these two demos are listed below:
http://plnkr.co/edit/9EaRfrSQggPETrXhNZvq?p=preview : using templateUrl
http://plnkr.co/edit/UHzEpugxtM6JjoNrUd9X?p=preview : using template

The only difference between directives myButton1 and myButton2 is :
myButton1 uses :
templateUrl: function (element, attrs) {
return TEMPLATE_ACTION;
}
The content of "actionTemplate.html" is:

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

myButton2 uses :
template: '<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;
                        }
                    };
                }
            ])
    ;

The result is that two buttons are displayed in the same line as below:
wrong result

But one use "template" in the directive, it works well:

        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;
                        }
                    };
                }
            ])
    ;

The result is as below:
right result

Upvotes: 1

Views: 81

Answers (1)

MMhunter
MMhunter

Reputation: 1441

There could be a known issue when using ng-repeat, templateUrl, ng-if and replace:true at the same time though it is said to be fixed multiple times.

Could be problems with the transclude logic inside angular.

ng-if and ng-repeat are two special directives in angular and at the same time, the DOM in templateUrl is loaded asynchronously and suspend the compilation. This complex situation will somehow generate the issue.

To avoid this, just use ng-show instead of ng-if, or template instead of templateUrl, or set a script template for the templateUrl to put it in $templateCache.

Known issue reference (or u can google more for yourself)

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

Upvotes: 0

Related Questions