1

I have this angularJS app which has a countdown timer. I want to execute a function after it becomes zero. It currently goes into negative after it reaches 0. How to achieve this?

Angular Code:

myApp.controller('MyController', ['$scope', '$timeout' ,function($scope, $http, $routeParams, $timeout) {
  $scope.counter = 5000;
    $scope.onTimeout = function(){
        $scope.counter--;
        mytimeout = $timeout($scope.onTimeout,1000);
    }
    var mytimeout = $timeout($scope.onTimeout,1000);
  }
}]);


testControllers.filter('formatTimer', function() {
  return function(input)
    {
        function z(n) {return (n<10? '0' : '') + n;}
        var seconds = input % 60;
        var minutes = Math.floor(input / 60);
        var hours = Math.floor(minutes / 60);
        return (z(hours) +':'+z(minutes)+':'+z(seconds));
    };
});

HTML:

<div><p>{{counter|formatTimer}}</p></div>

3 Answers 3

3

Simply stop calling it when the counter is 0:

$scope.onTimeout = function(){
  if (--$scope.counter > 0) {
    $timeout($scope.onTimeout, 1000);
  } else {
    // Call your function now that counter is 0
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

You need to call the function at least once for it to keep calling itself:jsfiddle.net/L05oepmv (which you did in your code above, your jsfiddle is different)
0

Depending on what else you are doing, you probably don't need to put your timeout method on the scope. Also, look at $interval instead. It's better suited for calling something continuously.

function decreaseCounter() {
  if(--$scope.counter <= 0) {
    $interval.cancel(intervalPromise);
    yourOtherFunction();  
  }
}

var intervalPromise = $interval(decreaseCounter, 1000);

https://docs.angularjs.org/api/ng/service/$interval

Comments

0

If you need a precise countdown (specially if the time span is large) you need to calculate the time spent using Date time function. Simply incrementing a counter each 1000 milliseconds 5000 times, doesen't guarantee that at the end, the real time spent will be exactly 5000 seconds!

You could try something like this:

Controller:

function MyCtrl($scope, $interval) {
  var intervalId;

  $scope.counter = 0;
  $scope.initialCountdown = 10;
  $scope.countdown = $scope.initialCountdown;

  $scope.timer = function(){
    var startTime = new Date();
    intervalId = $interval(function(){
        var actualTime = new Date();
        $scope.counter = Math.floor((actualTime - startTime) / 1000);
        $scope.countdown = $scope.initialCountdown - $scope.counter;
    }, 1000);
  };

  $scope.$watch('countdown', function(countdown){
    if (countdown === 0){
        $scope.stop();
    }
  });

  $scope.start = function(){
    $scope.timer();
  };

  $scope.stop = function(){
    $interval.cancel(intervalId);
  };

}

View:

<div ng-controller="MyCtrl">
  <div>Counter: {{counter}}</div>
  <div>Countdown in seconds: {{countdown}}</div>  
  <div>Countdown date time: {{countdown | secondsToDateTime | date:'HH:mm:ss'}}</div>  
  <button ng-click="start()">start</button>
  <button ng-click="stop()">stop</button>      
</div>

Filter secondsToDateTime:

myApp.filter('secondsToDateTime', [function() {
    return function(seconds) {
        return new Date(1970, 0, 1).setSeconds(seconds);
    };
}])

CHECK THE DEMO FIDDLE

Enjoy!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.