0

I'm playing with Angular Timer, what I want to do is to be able to change the "countdown" on event. I've tried this

<timer interval="1000" countdown="{{countdown}}">{{minutes}}:{{seconds}}</timer>

with the guts of my controller looking like

// setup
...
$scope.timerRunning = true;
$scope.countdown    = 10;
...

I want to be able to dynamically update the countdown based on conditions handled in my controller, e.g. have it add 10 on each complete ( I know how to deal with the event, it's just a matter of making the directive update the countdown)

3 Answers 3

4

You don't need the double curlies {{ ... }} in an attribute as it's already interpreted as an angular expression. So the following will set the attribute based on the scope variable countdown:

<timer interval="1000" countdown="countdown"/>{{minutes}}:{{seconds}}</timer>

with the following in your controller:

$scope.countdown= 120;

Dynamically Updating

The challenge is to dynamically update the timer. Directive attributes aren't watched, by default, on digest cycles. So once the countdown begins it doesn't check the attribute again. For instance if you used a button like this that updated countdown:

<button ng-click="setCountdown(20)">set to 20</button>

With this function

$scope.setCountdown = function(newVal) {
  $scope.countdown =newVal;
}

Clicking the button would update the countdown variable but the timer wouldn't be affected.

Solution

The authors of that timer directive have provided a timer start event we can use in the setCountdown function like so:

$scope.setCountdown = function(newVal) {
  $scope.countdown =newVal;
  $timeout(function(){
     $scope.$broadcast('timer-start');
  },0);
}

Here we update the countdown, then we issue timer-start event to restart the timer. Note that I issue the broadcast inside a $timeout to ensure that the attribute has been updated. Without that $timeout the results aren't consistent.

Demo

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

Comments

0

I would try using some kind of $watch to observe when you want to change the countdowns.

Make sure that the countdown variables in your directives' controllers are binded to the parent scope. (e.g. scope: {countdown: '='} or something similar)

Comments

0

I think you need to use the "=" isolate scope option in your directive to achieve this. From my understanding, this allows you to bind your controller property to your directive and vice versa.

You would need to change your countdown attr to use the controller object:

<timer interval="1000" countdown="countdown">{{minutes}}:{{seconds}}</timer>

Your controller would look something like this:

app.controller("TimerCtrl", function($scope) {
$scope.timerRunning = true;
$scope.countdown    = 10;
});

And your directive would be something along the lines of:

app.directive("timer", function() {
return {
    restrict: "E",
    transclude: true,
    scope: {
        countdown: "="
    },
    template: '<div ng-transclude></div>',
    link: function (scope, element) {
        scope.incrementCountdown = function (amount) {
            scope.countdown += parseint(amount, 10);
        }

        // something that would trigger the increment, could be whatever
        element.bind('click', function () {
            scope.incrementCountdown(10); // could also pull the param value from an attribute on your directive
        });
    }
}
});

This way if you change the countdown within the scope of your directive it should update the model in your controller as well.

I haven't run this code so it may not be error free and I'm an Angular n00b, so hopefully I'm not leading you astray, but I'm sure someone else will chime in if this is wrong. Good luck.

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.