Amyth
Amyth

Reputation: 32949

scope variable updates only the first time

I am facing a very strange issue, I am using angular js to create a stopwatch, I use the following code to update the timer.

$scope.seconds = $scope.minutes = $scope.hours = "00";

$scope.timer = {
    h: 0,
    m: 0,
    s: 0
};

$scope.runTimer = function() {
    console.log($scope.timer);
    $scope.timer.s++;
    if ($scope.timer.s >= 60) {
        $scope.timer.s = 0;
        $scope.timer.m++;
        if ($scope.timer.m >= 60) {
            $scope.timer.m = 0;
            $scope.timer.h++
        }
    }

    $scope.seconds = $scope.timer.s > 9 ? "" + $scope.timer.s : "0" + $scope.timer.s;
    $scope.minutes = $scope.timer.m > 9 ? "" + $scope.timer.m : "0" + $scope.timer.m;
    $scope.hours = $scope.timer.h > 9 ? "" + $scope.timer.h : "0" + $scope.timer.h;
    $scope.continueTimer();
};

$scope.continueTimer = function() {
    setTimeout($scope.runTimer, 1000);
};

But the problem is the value for scope variables seconds, minutes & hours is updated only the first time in the view, i.e. when the runTimer method is triggered by ng-click so the template changes from 00:00:00 to 00:00:01 and is then does not update..

Using the console, I checked that the value of $scope.seconds, $scope.minutes & $scope.hours is being updated properly but view is not reflecting the correct value.

Here is a plunker showing the exact problem I am facing. Any help will be appreciated. Thanks.

Upvotes: 2

Views: 511

Answers (1)

user3559224
user3559224

Reputation:

Use $scope.$digest() and check !$scope.$$phase before $scope.$digest()

if(!$scope.$$phase)
            {
              $scope.$digest();
            }

So your app.js file code should be look like

var app = angular.module('plunker', []);

    app.controller('MainCtrl', function($scope) {
        $scope.seconds = $scope.minutes = $scope.hours = "00";

        $scope.timer = { 
            h: 0,
            m: 0,
            s: 0
        };  

        $scope.runTimer = function() {
            console.log($scope.timer);
            $scope.timer.s++;
            if ($scope.timer.s >= 60) {
                $scope.timer.s = 0;
                $scope.timer.m++;
                if ($scope.timer.m >= 60) {
                    $scope.timer.m = 0;
                    $scope.timer.h++
                }   
            }   

            $scope.seconds = $scope.timer.s > 9 ? "" + $scope.timer.s : "0" + $scope.timer.s;
            $scope.minutes = $scope.timer.m > 9 ? "" + $scope.timer.m : "0" + $scope.timer.m;
            $scope.hours = $scope.timer.h > 9 ? "" + $scope.timer.h : "0" + $scope.timer.h;
            **if(!$scope.$$phase)
            {
              $scope.$digest();
            }**
            $scope.continueTimer();

        };  

        $scope.continueTimer = function() {
            setTimeout($scope.runTimer, 1000);
        };  
    });

See this working plunker

Upvotes: 3

Related Questions