我有一个父指令,我想在链接函数中动态添加子指令。 子指令^需要parentDirective 。 我可以添加任何html元素,但是一旦我尝试$ compile我的子指令,我得到以下错误,它无法找到所需的控制器。如果我手动添加子指令它完美地工作。
错误:
Error: [$compile:ctreq] Controller 'myInput', required by directive 'myKey', can't be found!
添加元素后,我的模板应如下所示:
<myInput>
<myKey></myKey> <-- added dynamically
<myKey></myKey> <-- added dynamically
<myKey></myKey> <-- added dynamically
....
</myInput>
myInput指令:
angular.module('myModule').directive('myInput', ['$log', '$templateCache', '$compile', function($log, $templateCache, $compile) {
return {
restrict: 'E',
transclude: true,
scope: {
service: '=', // expects a stimulus object provided by the tatoolStimulusService
onkeydown: '&' // method called on key press
},
controller: ['$scope', function($scope) {
this.addKey = function(keyCode, value) {
$scope.service.addInputKey(keyCode, { givenResponse: value });
};
}],
link: function (scope, element, attr) {
// add keys directives
angular.forEach(scope.service.registeredKeyInputs, function(value, key) {
var keyEl = angular.element(
$compile('<myKey code="'+ key +'" response="'+ value.response +'"></myKey >')($rootScope));
element.children(":first").append(keyEl);
});
},
template: '<div ng-transclude></div>'
};
}]);
myKey指令:
angular.module('myModule').directive('myKey', ['$log', '$sce', function($log, $sce) {
return {
restrict: 'E',
scope: {},
require: '^myInput',
link: function (scope, element, attr, myCtrl) {
myCtrl.addKey(attr.code, attr.response);
// ...
},
template: '<div class="key"><span ng-bind-html="key"></span></div>'
};
}]);
答案 0 :(得分:24)
将compile-append操作的顺序更改为append-compile:
var keyEl = angular.element('<myKey code="'+ key +'" response="'+ value.response +'"></myKey>');
element.append(keyEl);
$compile(keyEl)(scope);
在这种情况下(定位父元素指令)显然很重要,正在编译的新元素在DOM中已经已经。
除非将DOM元素附加到DOM,否则它不具有父项(其parentNode
属性为null
)。当Angular查找^myInput
时,它遍历DOM树,直到找到具有required指令的节点。如果该元素尚未在DOM中,则此搜索会立即失败,因为元素不具有单个parentNode
。因此你得到了错误。
我还建议将指令的名称从camelCase更改为snake-case:
<my-input>
<my-key></my-key>
</my-input>
然后编译部分也将改变:
angular.element('<my-key code="'+ key +'" response="'+ value.response +'"></my-key >');