$ compile嵌套指令来自另一个指令

时间:2014-03-21 16:37:11

标签: angularjs angularjs-directive

TL; DR; jsFiddle here

我想使用两个指令(kmOuterkmInner)作为嵌套指令:

<div km-outer>
    <div km-inner></div>
    <div km-inner></div>
    <!-- ... -->
</div>

所以我声明如下。请注意,内部指令需要外部控制器:

app.directive('kmOuter', function () {
    return {
        restrict: 'AC',
        scope: null,
        controller: function ($scope) {
            this.childAdded = function () {
                console.log('Child added.');
            };
        }
    };
});

app.directive('kmInner', function () {
    return {
        restrict: 'AC',
        require: '^kmOuter',
        template: '<div>Lorem ipsum</div>',
        link: function (scope, elem, attrs, kmOuterController) {
            kmOuterController.childAdded();
        }
    };
});

这很好用(.childAdded()正在被调用)。现在,我想动态插入内部指令的新实例。这个行动是由第三个不相关的指令触发的:

app.directive('kmChildAdder', function ($compile) {
    return {
        restrict: 'AC',
        scope: {
            target: '@kmChildAdder'
        },
        link: function (scope, elem) {
            console.log(scope);
            var target = document.querySelector(scope.target);

            angular.element(elem[0]).bind('click', function () {
                // Error is here
                var newInner = $compile('<div km-inner></div>')(scope)[0];
                target.appendChild(newInner);
            });
        }
    };
});

像这样使用:

<button km-child-adder="[km-outer]">Add child</button>

但它打破了以下信息:

Error: [$compile:ctreq] Controller 'kmOuter', required by directive 'kmInner', 
can't be found!

.childAdded()不再被召唤。

我该如何解决这个问题?或者这个设计本身可能会被破坏,我应该重新组织我的代码?

2 个答案:

答案 0 :(得分:3)

我想我是借鉴@Mobin Skariya的回答。

键是$compile只有插入的元素,而不是所有元素:

link: function (scope, elem) {
    var target = angular.element(document.querySelector(scope.target));

    angular.element(elem[0]).bind('click', function () {
        var newInner = angular.element('<div km-inner="param"/>');
        target.append(newInner);

        scope.$apply(function () {
            $compile(newInner)(scope);
        });
    });
}

我准备了jsFiddle with example,其中第三个不相关的指令插入广告编译内部指令与工作的双向数据绑定 - 你会发现它here。关于它的好处是第三个指令(kmChildAdder)可以插入内部指令,从多个独立的控制器中获取绑定。

答案 1 :(得分:1)

在您的代码中进行了一些编辑。 jsFiddle链接中提供的代码

link: function (scope, elem) {
            console.log(scope);
            var target = document.querySelector(scope.target);
            angular.element(elem[0]).bind('click', function () {
                var newInner = '<div km-inner></div>';
                angular.element(target).append(newInner);
                $compile(target)(scope)
            });
        }

检查这是否符合预期。