Добавить дочернюю директиву в родительской директиве
У меня есть родительская директива, где я хочу динамически добавлять дочерние директивы в функцию ссылки. Для дочерних директив ^ требуется parentDirective.
Я могу добавить любой элемент html, но как только я попытаюсь скомпилировать мою дочернюю директиву, я получаю следующую ошибку: он не может найти требуемый контроллер. Если я вручную добавляю дочерние директивы, он работает отлично.
Ошибка:
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>'
};
}]);
Ответы
Ответ 1
Измените порядок операций компиляции-добавления для добавления-компиляции:
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, пока не найдет node с требуемой директивой. Если элемент еще не находится в DOM, этот поиск не выполняется немедленно, потому что элемент не имеет одного parentNode
. Отсюда ошибка, которую вы получаете.
Также я рекомендую сменить имена ваших директив с camelCase на змеиный случай:
<my-input>
<my-key></my-key>
</my-input>
Затем компиляционная часть также изменится:
angular.element('<my-key code="'+ key +'" response="'+ value.response +'"></my-key >');