Arek ┼╗elechowski Arek ┼╗elechowski - 1 month ago 11
AngularJS Question

Angular is not able to find required controller in directive

I am trying to create series of directives which cummunicates via controller. This is what I have now:

angular.module('drmApp')
.directive('formInput', function () {
return {
templateUrl: 'views/directives/forminput.html',
restrict: 'E',
controller: 'ForminputCtrl',
controllerAs: 'ctrl',
bindToController: true,
transclude: true,
scope: {
model: '=',
errors: '=',
property: '@',
label: '@',
form: '=?',
},
link: function postLink(scope, element, attrs, ctrl, $transcludeFn) {
console.log($transcludeFn());
}
};
})
.directive('formInputValidationSummary', function() {
return {
restrict: 'E',
require: '^formInput',
transclude: true,
link: function postLink(scope, element, attrs, ctrl, $transcludeFn) {
ctrl.setValidationSummary($transcludeFn);
}
}
})
.directive('formInputContent', function() {
return {
restrict: 'E',
require: '^formInput',
transclude: true,
link: function postLink(scope, element, attrs, ctrl, $transcludeFn) {
ctrl.setInput($transcludeFn);
}
}
});


HTML Markup:

<form-input model="entity"
label="{{ 'WYKONAWCA_COLOR' | translate }}"
errors="errors"
property="color"
form="form">
<form-input-content>
<input colorpicker="rgb" ng-model="model.color" type="text">
</form-input-content>
</form-input>


Sadly, currently I am receiving this error:

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


I am using latest angular from v1.4 series. Also, this does not work with angular ~1.3. Is there something that I have forgot about? Did I misunderstand directive features?

Answer

Since you are transcluding transclude: true, Angular yanks the transcluded content out of the DOM - so, <form-input-content> is now not a child of <form-input>.

Then, when you are invoking the transclude function, this links the directive - and at that time it complains about not being able to find the parent formInput controller.

When you transclude, be sure to place the transcluded content back in the DOM:

link: function postLink(scope, element, attrs, ctrl, $transcludeFn) {
   $transcludeFn(function(transcludedContentClone){
      // this happens prior to linking of transcluded content
      element.append(transcludedContentClone);
   });

   // ...
}
Comments