Reputation: 4803
I'm trying to do something very simple, using the controller parameter of the link function for my directive, but it's being passed as 'undefined'. Can anyone tell me what I'm missing?
The HTML:
<div ng-app="myApp">
<div ng-controller="SampleCtrl" my-form >
<p> Click count: {{ count }} </p>
</div>
</div>
The Javascript:
myApp.controller('SampleCtrl', function($scope){
$scope.count = 0;
this.init = function(val) {
$scope.count = val;
}
});
myApp.directive('myForm', function() {
var linkFn = function(scope, elem, attrs, ctrl) {
ctrl.init(17); //Error here. ctrl is undefined
elem.bind('click', function() {
scope.$apply(function(){
scope.count++;
});
});
};
return linkFn;
});
Upvotes: 4
Views: 4669
Reputation: 3091
As Dan correctly askes in his comment on the accepted answer
Why in the world should a directive have to have any direct reference to a particular controller? Aren't they supposed to be nice and portable?
You not need to reference a controller to leverage the ctrl
parameter in a directive.
Instead you can use require: 'ngModel'
As the model will be defined inside a ng-controller scope value this creates your link to the controller without having to hard code the controller name.
Here's an exampled based off of a directive I use to set a form as invalid if an input file is too large.
myApp.directive('maxFileSize', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
var maxSize = Number(attrs.maxFileSize);
var sizeHandler = function () {
if (element.get(0).files.length) {
var fileSize = element.get(0).files[0].size; // in bytes
if (fileSize > maxSize) {
//console.log('file size is more than ' + maxSize + ' bytes!');
ctrl.$setValidity("fileSize", false);
} else {
ctrl.$setValidity("fileSize", true);
}
}
};
element.bind('change', sizeHandler);
}
};
});
Upvotes: 2
Reputation: 4803
It appears that my directive has to use the Directive Definition Object to return the link function and include a reference to the Controller as the 'controller' parameter of the ddo, like so:
myApp.directive('myForm', function() {
var linkFn = function(scope, elem, attrs, ctrl) {
ctrl.init("17"); //This now works, due to my return below
elem.bind('click', function() {
scope.$apply(function(){
scope.count++;
});
});
};
return {
controller: 'SampleCtrl',
link:linkFn};
});
Upvotes: -1
Reputation:
Instead of trying to work off the controller, could you work of the scope like I have done in this Plunk?
Upvotes: 1