htmlangularjsmath

Why is the counter decrementing correctly but the countdown is not?


Here is my angular code to define a countdown timer for my website:

function AlbumCtrl($scope, $timeout) {
  $scope.counter = new Date("Nov 30, 2017 09:00:00").getTime() - new Date().getTime();
  $scope.onTimeout = function() {
    $scope.counter--;
    var distance = $scope.counter;
    $scope.countdown = Math.floor(distance / (1000 * 60 * 60 * 24)) + "d " +
      Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) + "h " +
      Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) + "m " +
      Math.floor(((distance % (1000 * 60)) / 1000)) + "s ";
    if ($scope.counter > 0) {
      mytimeout = $timeout($scope.onTimeout, 1000);
    } else {
      alert("Time is up!");
    }
  }

  var mytimeout = $timeout($scope.onTimeout, 1000);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <!-- added for a working snippet -->


<!doctype html>
<html ng-app>

<head>
  <script src="http://code.angularjs.org/angular-1.0.0rc11.min.js"></script>
  <script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
</head>

<body>
  <div ng-controller="AlbumCtrl">
    {{counter}} {{countdown}}
  </div>
</body>

</html>

The 'counter' appears to decrement correctly on my page but the 'countdown' stays fixed and shows the correct value only on page load or refresh. For example, I get the following output as time passes:

    1115148833 12d 21h 45m 48s
    1115148745 12d 21h 45m 48s
    1115148693 12d 21h 45m 48s

What exactly is going wrong?


Solution

  • https://github.com/johnpapa/angular-styleguide/tree/master/a1

    // Declare a "main" module for the single page application
    // second argument to module is an array of dependencies your module
    // uses (examples: ui-router ui-bootstrap etc., 'ng' module is assumed as a dependency)
    angular.module('myApp', [])
    
    
    //Defining a service on the module allows you to encapsulate some functionality
    //Injecting the angular $timeout service from the 'ng' module and defining
    //a new service.  This object gets initialized the first time it's
    //referenced and stays alive until the application/page is refreshed.
    .service("CountdownService", function($timeout){
      //Define an object to attach properties and functions to and return for
      //use elsewhere in the app
      var countdownService = {};
      
      //Basically the functional code you had already adjusted the
      //seconds to just use %60 since some sort of issue with the existing math
      // %60 should give remainder after dividing by 60 and appears the "distance"
      // was moving at 1 second per second not 1000, so removed the 1000 factors
      countdownService.counter = new Date("Nov 30, 2017 09:00:00").getTime() - new Date().getTime();
      countdownService.onTimeout = function() {
        countdownService.counter--;
        var distance = countdownService.counter;
        
        var newValue = Math.floor(distance / (1000 * 60 * 60 * 24)) + "d " +
          Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) + "h " +
          Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)) + "m " +
          Math.floor((distance % (60)) ) + "s ";
        countdownService.countdown = newValue;
          
          console.log(Math.floor((distance % (60))) + "s ");
        if (countdownService.counter > 0) {
          mytimeout = $timeout(countdownService.onTimeout, 1000);
        } else {
          alert("Time is up!");
        }
      }
    
      var mytimeout = $timeout(countdownService.onTimeout, 1000);
      return countdownService;
    })
    
    //Now the controller just has the new service injected it uses "this"
    //instead of scope in the ng-controller we use "controllerAs" syntax
    //so we don't need to use the scope (angular 2 hides the scope so good
    //to just get used to not using it)
    .controller("TestCtrl", function(CountdownService){
      this.CountdownService = CountdownService;
    });
    <!doctype html>
    <html ng-app="myApp">
    
    <head>
    </head>
    
    <body>
      <div ng-controller="TestCtrl as testCtrl">
        {{testCtrl.CountdownService.counter}} {{testCtrl.CountdownService.countdown}}
      </div>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.js"></script> <!-- added for a working snippet -->
    </body>
    
    </html>