I have an AngularJS question that is driving me absolutely crazy. I have a service that looks like this (this is an example to illustrate the issue)
var app = angular.module('test-module');
app.service('ToolService', function($timeout){
this.doSomething = function() {
console.log("y u no referenced as method?!?");
}
this.runTimeoutExample = function(){
$timeout(function(){
this.doSomething();
}, 1000);
}
})
My controller looks like this:
var app = angular.module('test-module', []);
var ctrl = app.controller('main-controller', function($scope, ToolService) {
$scope.somethingWasClicked = function() {
ToolService.runTimeoutExample();
}
});
Here's the issue, when the button that was clicked that calls $scope.somethingWasClicked it forwards the call to the service and I get an error saying "this.doSomething is not a function".
Why? And how do I fix this? I'm having a hard time finding a way around needing my code to run like this without adding unnecessary logic into my controller.
Thanks in advance for your help
I have an AngularJS question that is driving me absolutely crazy. I have a service that looks like this (this is an example to illustrate the issue)
var app = angular.module('test-module');
app.service('ToolService', function($timeout){
this.doSomething = function() {
console.log("y u no referenced as method?!?");
}
this.runTimeoutExample = function(){
$timeout(function(){
this.doSomething();
}, 1000);
}
})
My controller looks like this:
var app = angular.module('test-module', []);
var ctrl = app.controller('main-controller', function($scope, ToolService) {
$scope.somethingWasClicked = function() {
ToolService.runTimeoutExample();
}
});
Here's the issue, when the button that was clicked that calls $scope.somethingWasClicked it forwards the call to the service and I get an error saying "this.doSomething is not a function".
Why? And how do I fix this? I'm having a hard time finding a way around needing my code to run like this without adding unnecessary logic into my controller.
Thanks in advance for your help
Share Improve this question asked Feb 26, 2016 at 16:33 the_caminothe_camino 3565 silver badges18 bronze badges 1- Please review stackoverflow./questions/20279484/… – charlietfl Commented Feb 26, 2016 at 18:23
3 Answers
Reset to default 14You have 2 options:
1) Using bind()
method of the function object:
Change the context of the timeout callback, to reach the controller this
:
this.runTimeoutExample = function(){
$timeout(function(){
this.doSomething();
}.bind(this), 1000);
}
2) Create a special variable self
, to keep the link to main service function context:
var app = angular.module('test-module');
app.service('ToolService', function($timeout){
var self = this;
self.doSomething = function() {
console.log("y u no referenced as method?!?");
}
self.runTimeoutExample = function(){
$timeout(function(){
self.doSomething();
}, 1000);
}
})
If every time using self
, you'll be sure that no context lost will happen.
Read more about the context of a function.
the function inside timeout has a different scope as it is not a function belonging to the controller. Assign this
to a variable before timeout, and then use that variable:
var app = angular.module('test-module');
app.service('ToolService', function($timeout){
this.doSomething = function() {
console.log("y u no referenced as method?!?");
}
this.runTimeoutExample = function(){
var self = this;
$timeout(function(){
self.doSomething();
}, 1000);
}
})
var app = angular.module('test-module',[]);
app.service('ToolService', function($timeout){
function doSomething() {
console.log("y u no referenced as method?!?");
}
this.runTimeoutExample = function(){
$timeout(function(){
doSomething();
}, 1000);
}
});
app.controller('main-controller', function($scope, ToolService) {
$scope.somethingWasClicked = function() {
ToolService.runTimeoutExample();
};
});
<script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test-module" ng-controller="main-controller">
<input type="button" value="click" ng-click="somethingWasClicked()">
</div>