I'm attempting to use $timeout to invoke one function that I have, but I don't know how to invoke a function that is in the $scope. Let me exemplify
I have this:
$scope.play = function(){
// function implementation
if(condition()){
$timeout(play, 1000);
}
}
it doesn't recognize the play function, I have also tried this
$timeout($scope.play, 1000);
and it also doesn't work. I had to work around it like this:
var play = function(){
$scope.playInner();
}
$scope.playInner = function(){
// function implementation
if(condition()){
$timeout(play, 1000);
}
}
But I'm sure there's a better way to do this, does anyone know how I can do that?
as JB Nizet suggested, $timeout($scope.play, 1000) should work fine.
Example:
function ctrl($scope,$timeout){
$scope.data=0;
$scope.play=function(){
$scope.data++;
$timeout($scope.play,1000);
}
}
Live example: http://jsfiddle.net/choroshin/wF8SZ/
Related
I have 2 controller say cont_a and cont_b which has function fun_a() and fun_b() respectively.
I have a button inside cont_a and if I click on it it should call both function, and I have no idea from where to begin with.
Thank you.
Two options, use a service or use an angular event
Service approach
app.service('funcService', function(){
this.fun_a = function (){
alert('fun_a')
}
this.fun_b = function (){
alert('fun_b')
}
}
app.controller('Ctrl_1' , function($scope,funcService){
$scope.callBothFunctions = function(){
funcService.fun_a();
funcService.fun_b()
}
});
app.controller('Ctrl_2' , function($scope,funcService){
$scope.func_b = funcService.func_b;
});
Event approach
app.controller('Ctrl_1' , function($scope,$rootScope){
$scope.fun_a = function (){
alert('fun_a');
$rootScope.$broadcast('call-fun_b');
}
});
app.controller('Ctrl_2' , function($scope){
$scope.fun_b = function (){
alert('fun_b')
}
$scope.$on('call-fun_b', function(){
$scope.fun_b();
})
});
Beyond this, question is too vague to know what best approach is. Generally using services is best way to keep controller code lean
Hello I'm new in angularJS. Suitable or not to implement function inside function?
For example like this:-
$scope.loadDistrict = function(id) {
// statement
$scope.loadBasedOnYear = function(y_id) {
console.log(y_id);
// statement
};
};
If you bind method on scope, it's available from view.
From your code
$scope.loadDistrict = function(id) {
// statement
$scope.loadBasedOnYear = function(y_id) {
console.log(y_id);
// statement
};
};
loadBasedOnYear won't available until loadDistrict is called.
It's very bad pattern to follow.
It is possible but without context I don't really know why you would do this, calling $scope.loadBasedOnYear before calling $scope.loadDistrict will result in an error so be careful with such a design pattern.
Yes this is fine.
You should watch out for when the function will be executed outside of angular's cycle. E.g. if you do:
setTimeout(function() { $scope.test = 5; }, 1000);
If you need to do this then you need to wrap the function in $scope.$apply(), or use $timeout.
I have an angular js controller that I am writing in a way so other controllers can inherit from it. Instead of defining the function as a single one in the angular's controller function I am writing it in the following way:
function SomeCtrl($scope)
{
this.some_field = "1234";
this.scope.externalMethod = angular.bind(this, this.externalMethod);
this.scope.anotherMethod = angular.bind(this, this.anotherMethod);
return this;
}
SomeCtrl.prototype.externalMethod = function()
{
//Do something
//....(Don't worry about this method, its just to highlight that I can call this method from $scope.externalMethod)
}
//These are the methods of interest
SomeCtrl.prototype.instanceMethodOne = function()
{
//Do something....
}
SomeCtrl.prototype.anotherMethod = function()
{
this.instanceMethodOne(); //---> Problem here!
//Carry on
//....
}
angular.module('some_module') //Previously defined
.controller('SomeCtrl', SomeCtrl)
So the problem that I am having now is to have a reference (this) inside the method "anotherMethod", which calls a class instance method "instanceMethodOne". This resolves to null as the self reference "this" is not resolved at that point. Is there any way to reference an object inside its instance method like in this case?
The problem has been resolved.
UPDATE AND FIXED:
Okay so I have looked into this problem. I should actually update the problem. It actually looks more like this:
function SomeCtrl($scope)
{
this.some_field = "1234";
this.scope.externalMethod = angular.bind(this, this.externalMethod);
this.scope.anotherMethod = angular.bind(this, this.anotherMethod);
return this;
}
SomeCtrl.prototype.externalMethod = function()
{
//Do something
//....(Don't worry about this method, its just to highlight that I can call this method from $scope.externalMethod)
}
//These are the methods of interest
SomeCtrl.prototype.instanceMethodOne = function()
{
//Do something....
}
SomeCtrl.prototype.anotherMethod = function()
{
var aCallBack = function()
{
//Some stuff...
this.instanceMethodOne(); //---> Problem here!
}
//Carry on
//....
}
angular.module('some_module') //Previously defined
.controller('SomeCtrl', SomeCtrl)
So the fix was to first create a reference to the object's method. That way I could call it within the callback function. The "this" in the callback function was referring to that function itself. Sorry for false alarm...This is fixed now! Thanks #sma for looking into it.
I have a ExtJS 4.2.1 Controller where I fires a function after 1 second using setTimeout:
onPrint: function () {
var me = this;
// start some stuff here...
// end some stuff here...
// wait 1 second and call checkDownloadComplete function
setTimeout(me.checkDownloadComplete, 1000);
},
checkDownloadComplete: function () {
var me = this;
// validate stuff here...
if (something == "true") {
return;
}
// first approach but didn't work (maybe because the scope)
setTimeout(me.checkDownloadComplete, 1000);
// sencond approach but didn't work
Ext.bind(function () {
setTimeout(checkDownloadComplete, 1000)
}, me)
},
My first try was to use:
setTimeout(me.checkDownloadComplete,1000); But this didn't work
My second try was to comment the last line, and use Ext.bind:
Ext.bind(funciton(){setTimeout(checkDownloadComplete,1000)},me);
Any clue what I'm doing wrong? Because none of those work to call again a function it self.
Thanks
UPDATE:
I also try this but without success:
setTimeout(Ext.bind(checkDownloadComplete,me), 1000);
The solution was to change both setTimeout calls to:
setTimeout(Ext.bind(me.checkDownloadComplete, me), 200);
The problem was that on the first call of the setTimeout, the checkDownloadComplete scope was changed to a setTimeout scope instead of controller scope, so changing both fixed the problem-
I am trying to implement the directive that is consuming the data from the service and reacts accordingly. However, something is going wrong and I need some assistance.
Here is the sample of the code that also can be found at http://jsfiddle.net/3c9h7/5/
var app = angular.module('myApp', []);
app.service('MyService', [
'$rootScope', function($rootScope) {
this.value = 4;
var self = this;
function inc(){
self.value += 3;
}
setInterval(inc, 1000);
}
]);
app.directive('myDir', ['MyService', function(MyService){
return {
link : function(scope, element){
function expr(){
return MyService.value;
}
function react(){
element.html(MyService.value);
}
scope.$watch(expr, react);
react();
}
}
}]);
<div ng-app='myApp'my-dir>
</div>
As the result Div element displaying the initial value of MyService.value but is ignoring the updates that happens in the service every second.
I have found the solution which involves rootScope(i.e. uncomment lines 7 and 9 in the jsFiddle sample):
function inc(){
$rootScope.$apply(function(){
self.value += 3;
});
}
setInterval(inc, 1000);
However, it does seem to be right to me..All the samples I found are not using this trick..So, am I missing something? Is "rootScope" solution appropriate? Maybe there is a better way to achieve the goal?
Thanks!
Use Angular's $interval (ref) instead of window.setInterval().
What it does though is actually calling apply() under the hoods, so your solution is correct, just a bit more complex. Also $interval can be mocked for testing.