Let's say I have the following two directives:
angular.module('demo').directive('functional', [function (){
var idempotentMethods = ['idempotentMethod', 'otherIdempotentMethod'];
return {
restrict: 'E',
scope: {
'demoObject': '='
},
templateUrl: 'directive.html',
link: function (scope){
for(var i = 0; i < idempotentMethods.length - 1; i++){
scope[idempotentMethods[i]] = function(){
scope.demoObject[idempotentMethods[i]]();
}
}
}
}
}]);
angular.module('demo').directive('nonFunctional', [function (){
var idempotentMethods = ['idempotentMethod', 'otherIdempotentMethod'];
return {
restrict: 'E',
scope: {
'demoObject': '='
},
templateUrl: 'directive.html',
link: function (scope){
for(var i = 0; i < idempotentMethods.length; i++){
scope[idempotentMethods[i]] = scope.demoObject[idempotentMethods[i]];
}
}
}
}]);
And the following factory:
angular.module('demo').factory('demoFactory', ['$resource', function(resource){
var DemoFactory = resource('demo.json');
angular.extend(DemoFactory.prototype, {
idempotentMethod: function () {
return this.$get();
},
otherIdempotentMethod: function () {
return this.$get();
}
});
return DemoFactory;
}]);
In the functional directive when scope.idempotentMethod() is triggered (through an ng-click
or otherwise), the INCORRECT Factory method gets called.
In the nonFunctional directive it triggers
TypeError: undefined is not a function
at Scope.angular.extend.idempotentMethod
at $parseFunctionCall
at callback
at Scope.$eval
In the Factories method.
This suggests two things.
1) The function reference is binding (as expected),however only the last function reference is binding.
2) The this
reference is incorrect. Printing out this
in the Factory methods appears to corroborate this, with the non-Functional directive producing Scope, while the functional directive produces a Resource.
What is causing these two behaviours? Why is the this reference binding incorrectly? Why is the wrong function being called?
A plunkr demoing the problem: http://plnkr.co/B52DV0jmSWXc0M6GAamM
I think it's the way you set the closure:
correct way:
[UPDATE]
In your code to pass the correct closure you can do:
Please note that i doesn't count to the end of idempotentMethods that is why your code executes
idempotentMethods[idempotentMethods.length-1]
when ng-click is triggered.