Reputation: 985
I have a controller function that I pass to a generic directive (#1). In the generic directive template I have have another specific directive (#2) to which I pass the same controller function.
The problem appears to be that the generic directive (#1) evals the controller method when it receives it and therefore does not pass it along correctly to the specific directive (#2) in the generic directive's template.
JSFIDDLE: http://jsfiddle.net/Hgh7D/
var myApp = angular.module('myApp',[])
.controller('myctrl', ['$scope', function($scope) {
$scope.ctrlfunc = function(myvar) {
console.log(myvar);
}
}])
.directive('mydir1', function() {
return {
template: '<div mydir2 dirfunc="dirfunc"></div>',
scope: {
dirfunc: '&'
}
}
})
.directive('mydir2', function() {
return {
template: '<button ng-click="onClick()">click</button>',
scope: {
dirfunc: '&'
},
link: function(scope) {
scope.onClick = function() {
scope.dirfunc({myvar:'hello'});
}
}
}
})
If I change the specific directive's scope declaration for the function to be '=' instead of '&' it works correctly.
JSFIDDLE: http://jsfiddle.net/Hgh7D/1/
.directive('mydir2', function() {
return {
template: '<button ng-click="onClick()">click</button>',
scope: {
dirfunc: '='
},
link: function(scope) {
scope.onClick = function() {
scope.dirfunc({myvar:'hello'});
}
}
}
})
However I do not want to do this because it may not always be used in this 2 layered directive situation. I would like it to remain '&' since it is expecting a function. Is this possible?
Upvotes: 2
Views: 146
Reputation: 20724
Unfortunately using '&' (namely in dir1) will cause the directive to run the function in the parent's scope so if you pass it to another child, it will no longer be active. One workaround is to define dir2
's link function like so:
link: function(scope, element, attrs) {
scope.onClick = function() {
scope.dirfunc({myvar:'hello'});
}
attrs.$observe("dirfunc", function (fn) {
if ("dirfunc" in scope.$parent) {
scope.dirfunc = scope.$parent.dirfunc;
}
});
}
The logic within $observe
allows it to either inherit from it's parent in the case of your layered case or when it's not layered. This isn't the cleanest solution and probably won't work if it's more than a single layer deep but it does work in your example.
Updated fiddle: http://jsfiddle.net/LyA9w/
Upvotes: 1