angular timer directive not working with ionic framework

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?

Answers:

Answer

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.

Answer

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

also use $broadcast events for control this directive

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

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,
     };
    }]);
    
Answer

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>
Answer

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>

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.