Stop time interval during navigation in angularjs - javascript

Currently i am using angular js
I have one get method to get data from server side in default.html page
function bindActiveLoans() {
$http.get(rootUrlSingleEscaped + '/cooperativa/allunfundedloans/?authId=' + userInfo.UserId)
.success(function (response) {
if (response.Loans.length == 0) {
$scope.IsValues = false;
$scope.$apply();
return true;
}
$scope.IsValues = true;
$scope.unfundedLoans = response;
});
};
setInterval(function () {
$scope.$apply(bindActiveLoans());
}, 5000);
The above function helps to get the data from server side method in every 5 seconds.
Here, I have an issue.
Additionally I have some more pages, like
default2.html,default3.html,default4.html,default5.html.
The timer is still running while i navigation default.html page to default1.html page. I want to only that timer running in default.html page.If i go to another page,then the timer should stop. How can we achieve it?

From the angularjs example in the $interval API page.
var interval = $interval(function() {
console.log('say hello');
}, 1000);
$interval.cancel(interval);
With $interval.cancel(var) you can stop the interval and if you want to stop it when navigating to another page you should try something like this.
var interval = null;
module.controller('SomeController', '$interval', function($interval) {
interval = $interval(function() {
...
}, 2000);
}).run(['$rootScope', '$interval', function($rootScope, $interval) {
$rootScope.$on('$routeChangeStart', function() {
$interval.cancel(interval);
});
}]);

You can listen to the $routeChangeStart event and do the clearing of the interval depending on the route parameters,
$scope.$on('$routeChangeStart', function (scope, next, current) {
if(<next is not default.aspx>){
// clear interval here
}
});

call clearInterval function when navigating from default page
e.g.
var myVar = setInterval(function () {
$scope.$apply(bindActiveLoans());
}, 5000);
function myStopFunction()
{
clearInterval(myVar);
}
Call myStopFunction

Related

Reset scope interval in angularjs directive creating loop

In my agnularjs directive I've got object containting logic of some script
$scope.slider = {
increment: 0,
step: 1,
positionTop: 0,
init: function (step, isClick) {
if(isClick) clearInterval($scope.interval);
...rest of script...
and then below, after $scope.slider is closed (}) I have this code
$timeout(function () {
$scope.slider.changeSlide($scope.slider.step);
$scope.interval = setInterval(function () {
$scope.slider.step++;
if($scope.slider.step === 5) $scope.slider.step = 1;
$scope.slider.changeSlide($scope.slider.step);
}, 5000);
});
On page load I'm starting init method work and then when user additionaly click this html tag
<span class="main__last-added-dot"
data-ng-class="slider.step == 1 ? 'main__last-added-dot--active' : ''"
data-ng-click="slider.init(1, true);"></span>
it clear interval which means that it stop working and I'm not seting new interval because I dont know how. I'm using angularjs $timeout to start interval because div which I'm working on are gathered in backend call so I need to wait for them.
I tried to assign interval to another scope variable and call it within like this
in init method within $scope.slider object:
$timeout(function(){ $scope.startInterval() });
below $scope.slider object:
$timeout(function () {
$scope.startInterval = function() {
$scope.interval = setInterval(function () {
console.log('fire function interval');
$scope.slider.step++;
if($scope.slider.step === 5) $scope.slider.step = 1;
$scope.slider.changeSlide($scope.slider.step);
}, 5000);
};
$scope.startInterval();
});
But it create some kind of loop I don't really know it was working very strange.
What I'm doing wrong how to stop this interval and start it again, after span click i want to clear seconds to 0..
I add demo.
You can do something like this below code, also please check this working plunker example for your given scenario.
Directive:
app.directive('myElement', ['$interval', '$timeout',
function($interval, $timeout) {
return {
restrict: 'E',
templateUrl: 'template.html',
link: function(scope) {
scope.timer=5000;
scope.step = 1;
function updateTime() {
if(scope.step==4) scope.step=0;
scope.step++;
}
scope.stopTime = $interval(updateTime, scope.timer);
scope.resetTimer=function(step){
scope.step = step;
$interval.cancel(scope.stopTime);
scope.stopTime = $interval(updateTime, scope.timer);
}
}
}
}]);
You should name your function and reset its interval in init like this:
$scope.slider = {
increment: 0,
step: 1,
positionTop: 0,
init: function (step, isClick) {
if(isClick) clearInterval($scope.interval);
$scope.interval = setInterval(intervalSlide, 5000); // Reset interval here
...rest of script...
};
// Name your function, no need to attach it to $scope
function intervalSlide() {
$scope.slider.step++;
if($scope.slider.step === 5) $scope.slider.step = 1;
$scope.slider.changeSlide($scope.slider.step);
}
$timeout(function () {
$scope.slider.changeSlide($scope.slider.step);
$scope.interval = setInterval(intervalSlide, 5000);
});

$interval not working for callback function, angular js

I am a beginner of angularjs, sorry if i asked silly question.
function getCams(callback){
var media_list = [];
MediaStreamTrack.getSources(function(sourceInfos){
var i=0;
while(i!=sourceInfos.length){
if (sourceInfos[i].kind == 'video'){
var temp = [];
temp.push(sourceInfos[i].id);
temp.push(sourceInfos[i].label);
media_list.push(temp);
}
i++;
}
callback(media_list);
});
}
var app = angular.module('myApp', []).config(function($interpolateProvider){
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});
app.controller('myCtrl', function($scope, $interval) {
$scope.cams = [];
var checkcams = getCams(function(media_list){
$scope.cams=media_list;
$scope.$apply();
console.log("test");
});
$interval(checkcams, 10000);
});
Above is the code from where i am trying to get the number of cams connected to a system, and trying to update the same in angular js using callback function, In this line
$interval(checkcams, 10000);
I am trying to call that function after every 10 secs but this function run only once after the page load, and not running after every 10 secs.
I already have a look at this question, it wont help me out.
$interval not running, angularjs
getCams is returning nothing hence $interval is not working. This is expected behavior.
You can rewrite your code as
//Wrap getCams call in a function
var checkcams = function(){
getCams(function(media_list){
$scope.cams=media_list;
$scope.$apply();
console.log("test");
});
}
//Call it when view is launched
checkcams();
//set Interval
$interval(checkcams, 10000);
By doing this
var checkcams = getCams(function(media_list){
$scope.cams=media_list;
$scope.$apply();
console.log("test");
});
You have set checkcams to be a variable of whatever getCams returns, not a function.
Try this instead
function checkcams () {
getCams(function(media_list){
$scope.cams=media_list;
$scope.$apply();
console.log("test");
});
}
$interval(checkcams, 10000);

How to pass variable asyncronously through different scripts

I can't figure out how to do it.
I have two separate scripts. The first one generates an interval (or a timeout) to run a specified function every x seconds, i.e. reload the page.
The other script contains actions for a button to control (pause/play) this interval.
The pitfall here is that both sides must be asyncronous (both run when the document is loaded).
How could I properly use the interval within the second script?
Here's the jsFiddle: http://jsfiddle.net/hm2d6d6L/4/
And here's the code for a quick view:
var interval;
// main script
(function($){
$(function(){
var reload = function() {
console.log('reloading...');
};
// Create interval here to run reload() every time
});
})(jQuery);
// Another script, available for specific users
(function($){
$(function(){
var $playerButton = $('body').find('button.player'),
$icon = $playerButton.children('i');
buttonAction = function(e){
e.preventDefault();
if ($(this).hasClass('playing')) {
// Pause/clear interval here
$(this).removeClass('playing').addClass('paused');
$icon.removeClass('glyphicon-pause').addClass('glyphicon-play');
}
else {
// Play/recreate interval here
$(this).removeClass('paused').addClass('playing');
$icon.removeClass('glyphicon-play').addClass('glyphicon-pause');
}
},
buttonInit = function() {
$playerButton.on('click', buttonAction);
};
buttonInit();
});
})(jQuery);
You could just create a simple event bus. This is pretty easy to create with jQuery, since you already have it in there:
// somewhere globally accessible (script 1 works fine)
var bus = $({});
// script 1
setInterval(function() {
reload();
bus.trigger('reload');
}, 1000);
// script 2
bus.on('reload', function() {
// there was a reload in script 1, yay!
});
I've found a solution. I'm sure it's not the best one, but it works.
As you pointed out, I eventually needed at least one global variable to act as a join between both scripts, and the use of a closure to overcome asyncronous issues. Note that I manipulate the button within reload, just to remark that sometimes it's not as easy as moving code outside in the global namespace:
Check it out here in jsFiddle: yay! this works!
And here's the code:
var intervalControl;
// main script
(function($){
$(function(){
var $playerButton = $('body').find('button.player'),
reload = function() {
console.log('reloading...');
$playerButton.css('top', parseInt($playerButton.css('top')) + 1);
};
var interval = function(callback) {
var timer,
playing = false;
this.play = function() {
if (! playing) {
timer = setInterval(callback, 2000);
playing = true;
}
};
this.pause = function() {
if (playing) {
clearInterval(timer);
playing = false;
}
};
this.play();
return this;
};
intervalControl = function() {
var timer = interval(reload);
return {
play: function() {
timer.play();
},
pause: function(){
timer.pause();
}
}
}
});
})(jQuery);
// Another script, available for specific users
(function($){
$(function(){
var $playerButton = $('body').find('button.player'),
$icon = $playerButton.children('i'),
interval;
buttonAction = function(e){
e.preventDefault();
if ($(this).hasClass('playing')) {
interval.pause();
$(this).removeClass('playing').addClass('paused');
$icon.removeClass('glyphicon-pause').addClass('glyphicon-play');
}
else {
interval.play();
$(this).removeClass('paused').addClass('playing');
$icon.removeClass('glyphicon-play').addClass('glyphicon-pause');
}
},
buttonInit = function() {
$playerButton.on('click', buttonAction);
interval = intervalControl();
};
buttonInit();
});
})(jQuery);
Any better suggestion is most welcome.

AngularJS + Ionic is truncating scope value after the return from second page to the main page.

I have following code in the "First" Ctrl of the my app, which is displaying timer for countdown.
Everything is working absolutely fine until i visited second page which is in the app.js defined by this way:
.state('app.home', {
url: '/home:playlistData',
views: {
'menuContent' :{
templateUrl: 'templates/home.html',
controller: 'HomeCtrl'
}
}
})
.state('app.saved', {
url: '/saved',
views: {
'menuContent' :{
templateUrl: 'templates/saved.html',
controller: 'SavedCtrl'
}
}
})
If i came back from second view to the first counter is still displayed but value in the
$scope.minutesLeft
Is not updated but
setInterval
function is still executing the code in the background and updated data values are still holded in the Dataholdingservice.
I tried scope apply and timeout functions, but without the luck.
Could somebody tell me how can i solve this issue?
Many thanks for any help.
Code of the HomeCtrl for countdown timer is following:
$scope.setTimer = function(timer) {
console.log(timer);
$scope.timer = timer;
};
$scope.saveTimer = function(timer) {
if($scope.selectedSounds.length == 0) {
$scope.showAlert("Add some sounds", "Cannot run timer for empty list");
} else {
$scope.clearCountDownAnimation();
var animationTimerId = setInterval(function () {
$("#minutesLeft").fadeTo(100, 0.1).fadeTo(200, 1.0);
}, 1000);
Dataholdingservice.setAnimationId(animationTimerId);
Dataholdingservice.setMinutesLeft(timer);
$scope.closePopover();
$scope.countDown();
}
};
$scope.clearCountDownAnimation = function() {
$("#minutesLeft").clearQueue().finish();
// Clear previously set animations
console.log(Dataholdingservice.getAnimationId());
if (Dataholdingservice.getAnimationId() != null) {
console.log("Interval cleared");
clearInterval(Dataholdingservice.getAnimationId());
}
};
$scope.countDown = function() {
var minutesLeft = Dataholdingservice.getMinutesLeft();
$scope.minutesLeft = minutesLeft;
$scope.isCounterDisplayed = Dataholdingservice.isCounterDisplayed();
var timerId = setInterval(function() {
console.log("Counting down");
minutesLeft -- ;
console.log("Decreasing minutes");
console.log(minutesLeft);
Dataholdingservice.setMinutesLeft(minutesLeft);
console.log("minutes left " + Dataholdingservice.getMinutesLeft());
$scope.$apply(function () {
$scope.minutesLeft = Dataholdingservice.getMinutesLeft();
});
if(minutesLeft <= 0) {
console.log("Time left");
clearInterval(Dataholdingservice.getTimerId());
clearInterval(Dataholdingservice.getAnimationId());
console.log(Dataholdingservice.isCounterDisplayed());
$scope.hideCounter();
$scope.stopAllSelectedSounds();
}
}, 1000 * 1);
Dataholdingservice.setTimerId(timerId);
};
$scope.hideCounter = function() {
console.log("Hidding the counter");
$scope.isCounterDisplayed = false;
$scope.$apply();
};
$scope.cancelTimer = function() {
clearInterval(Dataholdingservice.getTimerId());
clearInterval(Dataholdingservice.getAnimationId());
$("#minutesLeft").hide();
$ionicLoading.show({
duration: 500,
template: 'Timer canceled'
});
};
Since the $scope.minutesLeft is a primitive datatype, sometimes the changes happening in the controller will not get reflected in the view. You can create an object like $scope.viewModel = {} and then add the minutesLeft as a property to it like $scope.viewModel.minutesLeft = mintesLeft in your countdown function and bind viewModel.minutesLeft to the view. you should see the value getting updated properly.
I am not sure of your exact requirement, but I have put together the code for creating a simple timer that runs in the background in an angular service. The working code is available at http://codepen.io/svswaminathan/pen/MYXOPM

cancelling angularjs timeout after route change not working

I'm have a timer that polls a server for data every 10 seconds. However, everytime a user switches to another controller, the timer should get destroyed. For some reason it's not happening with my code below. The timer keeps polling the server regardless if I change controllers.
controller.js
$scope.init = function() {
//timer and timer stoper
$scope.counter= 0;
var mytimeout = $timeout($scope.onTimeout, 10000);
$scope.$on('$locationChangeStart', function() {
$timeout.cancel(mytimeout);
});
};
$scope.onTimeout = function() {
//polling server function
$scope.counter++;
var mytimeout = $timeout($scope.onTimeout, 10000);
var increase = 0;
inboxServ.check_newusers().then(function(data) {
if (data == "true") {
$scope.retrieveusers(increase);
}
});
};
It seems like you have a scope issue. You have $scope.init() which creates a timeout (held by mytimeout) and also wires up logic to cancel it if you start to change location. However, the function executed (onTimeout) starts another timeout, but assigns it to a different locally scoped mytimeout.
I would expect it, as is, to cancel the first timeout if you change location within the first 10 seconds, and fail to do so any time after that because the variables are different.
It might be as simple as changing it to something like this:
$scope.init = function() {
//timer and timer stoper
$scope.counter= 0;
$scope.mytimeout = $timeout($scope.onTimeout, 10000);
$scope.$on('$locationChangeStart', function() {
$timeout.cancel($scope.mytimeout);
});
};
$scope.onTimeout = function() {
//polling server function
$scope.counter++;
$scope.mytimeout = $timeout($scope.onTimeout, 10000);
var increase = 0;
inboxServ.check_newusers().then(function(data) {
if (data == "true") {
$scope.retrieveusers(increase);
}
});
};

Categories