带有ng-repeat的嵌套指令会导致奇怪的行为

时间:2016-07-01 14:19:09

标签: javascript angularjs angularjs-ng-repeat transclusion

我们假设我有2个指令:外部和内部。在第一个指令中,我有一些数据,我想在其中插入带有ng-repeat的第二个指令。所以我的指令看起来像:

outer.js

directive('outer', function($compile) {
    return {
        restrict: 'E',
        template: '<div class="options"></div>',
        scope: true,
        bindToController: {
            options: '='
        },
        link: function(scope, element) {
            var list = $(element).find('.options');
            // Here we dynamically insert html for second directive
            $('<inner><span ng-bind="$select.getValue(item)"></span></inner>').appendTo(list);
            $compile(list.contents())(scope);
        },
        controllerAs: '$select',
        controller: function($rootScope) {
            this.items = ['aaa', 'bbb'];

            this.getValue = function(item) {
                $rootScope.log += '\n' + item;
                return item;
            };
        }
    };
}

inner.js

directive('second', function($compile) {
    return {
        restrict: 'E',
        require: '^first',
        replace: true,
        transclude: true,
        template: '<ul><li><span></span></li></ul>',
        link: function(scope, element, attrs, $select, transclude) {
            var choices = $(element.find('li')[0]);
            choices.attr('ng-repeat', 'item in $select.items');

            var inner = $(choices.find('span')[0]);
            transclude(scope, function(clone) {
                inner.append(clone);
            });
            $compile(choices)(scope);
        }
    };
});

所以,在我的例子中,在每个$ digest循环中,$ select.getValue应该被调用两次:for&#39; aaa&#39;并为&#39; bbb&#39;。但实际上它调用了3次,第一次调用undefined,但我不明白为什么

有什么想法吗?

参见示例:

&#13;
&#13;
var myApp = angular.module('myApp', []);

myApp.directive('outer', function($compile) {
        return {
            restrict: 'E',
            template: '<div class="options"></div>',
            scope: true,
            bindToController: {
                options: '='
            },
            link: function(scope, element) {
                var list = $(element).find('.options');
                $('<inner><span ng-bind="$select.getValue(item)"></span></inner>').appendTo(list);
                $compile(list.contents())(scope);
            },
            controllerAs: '$select',
            controller: function($rootScope) {
                this.items = ['aaa', 'bbb'];

                this.getValue = function(item) {
                		$rootScope.log += '\n' + item;
                    return item;
                };
            }
        };
    })
    .directive('inner', function($compile) {
        return {
            restrict: 'E',
            require: '^outer',
            replace: true,
            transclude: true,
            template: '<ul><li><span></span></li></ul>',
            link: function(scope, element, attrs, $select, transclude) {
                var choices = $(element.find('li')[0]);
                choices.attr('ng-repeat', 'item in $select.items');

                var inner = $(choices.find('span')[0]);
                transclude(scope, function(clone) {
                    inner.append(clone);
                });
                $compile(choices)(scope);
            }
        };
    });
&#13;
.log {
  white-space: pre;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body ng-app="myApp">
  <span class="log" ng-bind="log"></span>    
  <outer></outer>  
</body>
&#13;
&#13;
&#13;

0 个答案:

没有答案