10

I am having issues with implementing the angular timer directive with the ionic framework. http://siddii.github.io/angular-timer/

When I implement the code using bower or the google cdn I have no issues.

    <!DOCTYPE html>
    <html>
    <head>
    <title>Plain Javascript Timer Example</title>
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="../app/js/timer.js"></script>
    <script>
    function startTimer() {
    document.getElementsByTagName('timer')[0].start();
    }
    function stopTimer() {
    document.getElementsByTagName('timer')[0].stop();
    }
    </script>
    </head>
    <body>
    <div>
    <h2>Plain JavaScript - Timer Example</h2>
    <h3><timer ng-app="timer"/></h3>
    <button onclick="startTimer()">Start Timer</button>
    <button onclick="stopTimer()">Stop Timer</button>
    </div>
    <br/>
    </body>
    </html>

However when I use the ionic bundle http://code.ionicframework.com/1.0.0-beta.13/js/ionic.bundle.js I can not get the timer to work. And do not seem to get any errors in the console.

Is this a known issue?

What would be stopping it from working?

Is there an alternate timer that people can reccomend? This one seemed the best to me?

3
  • 2
    This example seems likely to be unreliable simply because you're doing non-angular logic to an angular directive which is itself the entire app. Can you create a plunker and perhaps code the buttons in angular itself to rule out potential bugs? Commented Nov 9, 2014 at 7:38
  • 1
    had a look at the code of angular-timer, though its name says angular-timer, but the way it works $on, $broadcast and uses id's for starting stopping etc, I wont choose it personally in my production code, its not implemented in angular way sadly.... I have my own little timer implementation, though not as polish but does the job for me, I can share the code if you wish to move on from angular-timer Commented Nov 12, 2014 at 5:33
  • @harish thanks for the tip that would be great if you were happy to? As you say it sounds like there may be some limitations with this directive Commented Nov 12, 2014 at 8:44

5 Answers 5

7
+50

try looking at this code sample here: http://siddii.github.io/angular-timer/examples.html#/angularjs-single-timer

starting the timer in angular is done via

$scope.$broadcast('timer-stop');

not

element.start();

BTW, your ng-app should be in the html/body tag, not in the timer tag.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the info! I got a working eg here codepen.io/anon/pen/emYOeX one thing I can't work out though is how to persist the timer so that it continues counting even when I click between tabs. eg in my codepen it resets every time I click contact. Can you point me into the right direction here? Or is this not possible with this directive?
according to this - siddii.github.io/angular-timer/index.html#/markup you should add autostart="false"
and mabe use start-time attribute, to set the previous stopped time as the new starting time. You could probably save the previous stopped time with the timer-stopped event
4

here's angular way: http://plnkr.co/edit/ug4VqTkkFWlsYLy7uq4O

also use $broadcast events for control this directive

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

Comments

3

as per the discussion in comments, I am sharing the implementation of basic directive that I am using. This is not as generic as angular-timer, so you might need to tweak the little to suit your need.

first part : factory to hold the timer, start/stop, etc etc

csapp.factory("timerfactory", function () {
    var refresh = {
        suspend: false,
        pause: function () { refresh.suspend = true; },
        cont: function () { refresh.suspend = false; },
        toggle: function () { refresh.suspend = !refresh.suspend; },
        refreshText: function () { return refresh.suspend ? "Resume Refresh" : "Pause Refresh"; }
    };

    var timer = {
        timePending: 0,
        refreshInterval: 60,
        reset: function () { timer.timePending = timer.refreshInterval; },
        update: function () {
            if (timer.timePending < 0) timer.reset();
            timer.timePending--;
        },
        done: function () { return timer.timePending <= 0; },
        force: function () { timer.timePending = 0; }
    };

    return {
        refresh: refresh,
        timer: timer
    };
});

second part : the directive, which supports 2 operations

  1. boolean pause variable with 2 way binding

  2. on-timeout function : which will be called on timeout

  3. interval : in seconds, after which the on-timeout function would be called

    csapp.directive("csAutoRefresh", ["timerfactory", "Logger", "$interval", function (factory, logManager, $interval) {

    var $log = logManager.getInstance('csAutoRefresh');
    
    var templateFn = function () {
        var template = '<div class="text-left alert alert-success nopadding"';
        template += 'style="margin-bottom: 0; margin-right: 0"> ';
        template += ' <button class="btn btn-link" data-ng-click="factory.refresh.toggle()">';
        template += '{{factory.refresh.refreshText()}}</button>';
        template += '<span>...Refreshing upload status in ';
        template += ' {{factory.timer.timePending}} seconds</span>';
        template += ' </div>';
        return template;
    };
    
    var linkFn = function (scope) {
        scope.pauseOn = false;
        scope.isprocessing = false;
        scope.factory = factory;
        if (angular.isDefined(scope.interval) && collosys.isNumber(parseInt(scope.interval)) && parseInt(scope.interval) > 0) {
            scope.factory.timer.refreshInterval = scope.interval;
        }
        factory.timer.reset();
    
        scope.$watch(function () {
            return factory.timer.timePending;
        }, function () {
            if (!factory.timer.done()) return;
            var result = scope.$eval(scope.onTimeout);
            if (angular.isObject(result) && angular.isFunction(result.then)) {
                scope.isprocessing = false;
                factory.timer.reset();
                result.finally(function () {
                    factory.timer.reset();
                });
            };
        });
    
        scope.$watch('pauseOn', function () {
            if (scope.pauseOn) {
                factory.refresh.pause();
            } else {
                factory.timer.reset();
                factory.refresh.cont();
            }
        });
    
        var updateTimer = function () {
            if (scope.isprocessing) return;
            if (factory.refresh.suspend) return;
            factory.timer.update();
        };
    
        var interval = $interval(updateTimer, 1000);
        scope.$on('$destroy', function () {
            $interval.cancel(interval);
        });
    };
    
    return {
        restrict: 'E',
        scope: { onTimeout: '&', pauseOn: '=', interval: '@' },
        template: templateFn,
        link: linkFn,
     };
    }]);
    

2 Comments

@ak85 i havent written tests for this, but it works.
I had a look at this and it looks quite useful, it looked at though it was mainly focused on counting down? So I provided an answer which you can see in the list which has what I decided to use instead. Thanks for the advice re the angular timer though, I think I have a better result which I can easily customise for my own needs going forward.
2

I decided to not user the angular-timer directive as I was having issues with it reseting when ever I would change tabs as you can see from this example here.

Instead I based my timer of this fiddle.

You can see my final result in this pen. Which loads a timer in ionic, and maintains counting even whilst changing tabs. Going forward, would probably want to add some more changes to it such as can only click stop when the timer has started etc.

        <script id="home.html" type="text/ng-template">
          <ion-view title="Home">
            <ion-content class="padding">
              <p>Home page</p>
                <h1>{{myStopwatch.data.hours | numberFixedLen:2}}:{{myStopwatch.data.minutes | numberFixedLen:2}}:{{myStopwatch.data.seconds | numberFixedLen:2}}</h1>
                <button ng-click='myStopwatch.start()'>Start</button>
                <button ng-click='myStopwatch.stop()'>Stop</button>
                <button ng-click='myStopwatch.reset()'>Reset</button>          
            </ion-content>
          </ion-view> 
        </script>

    <script>
    .filter('numberFixedLen', function () {
        return function (n, len) {
            var num = parseInt(n, 10);
            len = parseInt(len, 10);
            if (isNaN(num) || isNaN(len)) {
                return n;
            }
            num = ''+num;
            while (num.length < len) {
                num = '0'+num;
            }
            return num;
        };
    })
    .constant('SW_DELAY', 1000)
    .factory('stepwatch', function (SW_DELAY, $timeout) {
        var data = {
            seconds: 0,
            minutes: 0,
            hours: 0
        },
        stopwatch = null;

        var start = function () {
            stopwatch = $timeout(function () {
                data.seconds++;
                if (data.seconds >= 60) {
                    data.seconds = 00;
                    data.minutes++;
                    if (data.minutes >= 60) {
                        data.minutes = 0;
                        data.hours++;
                    }
                }
                start();
            }, SW_DELAY);
        };

        var stop = function () {
            $timeout.cancel(stopwatch);
            stopwatch = null;
        };

        var reset = function () {
            stop()
            data.seconds = 0;
        };
        return {
            data: data,
            start: start,
            stop: stop,
            reset: reset
        };
    })
    .controller('HomeTabCtrl', function($scope, $state, stepwatch) {
      $scope.myStopwatch = stepwatch;
    });
    </script>

1 Comment

checkout my another answer on stopwatch in examination example
2

as per your comments, I am providing another answer... the stopwatch factory, that I am using in my project. as per your requirement you can use service like below :

checkout the PLUNKER to have a practical example.

  1. Initially you see instruction page, where timer is initialized to 2 hours.

  2. Then move to questions 1, where timer starts

  3. from question 1 you can go to help page, where the timer pauses

  4. then you move back to question 2, where timer resumes...

on how to use :

  1. start init it on first page

    app.controller('view1Ctrl', function($scope, $csCountdown){
      $csCountdown.init(2 * 3600); // 2 hours
      $scope.countdown = $csCountdown.data;
    })
    
  2. start the counter on second page

    app.controller('view2Ctrl', function($scope, $csCountdown){
      $csCountdown.start();
      $scope.countdown = $csCountdown.data;
    })
    

you can display the value on any page using countdown.stringValue

<h1>Time : {{countdown.stringValue}}</h1>

1 Comment

thanks for the plunker practical example. very helpful.

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.