TheGPWorx
TheGPWorx

Reputation: 887

How to use directive multiple times

Basically I have copied this code from another source which is a countdown timer.

Directive

app.directive('countdown', [
    'Util', '$interval', function (Util, $interval) {
        return {
            restrict: 'E',
            scope: {
                date: '@'
            },
            templateUrl: 'countdown_timer.html',
            link: function (scope, element) {
                var future = new Date(scope.date);

                var stop;

                stop = $interval(function () {
                    var diff;
                    diff = Math.floor((future.getTime() - new Date().getTime()) / 1000);

                    if (parseInt(diff) <= 0) {
                        stopTimer();
                        scope.days = 0;
                        scope.hours = 0;
                        scope.minutes = 0;
                        scope.seconds = 0;
                    } else {
                        var d = Util.dhms(diff);
                        scope.days = d[0];
                        scope.hours = d[1];
                        scope.minutes = d[2];
                        scope.seconds = d[3];
                    }
                }, 1000);

                stopTimer = function () {
                    console.log("Should Stop");
                    $interval.cancel(stop);
                };
            }
        };
    }
]).factory('Util', [
    function () {
        return {
            dhms: function (t) {
                var days, hours, minutes, seconds;
                days = Math.floor(t / 86400);
                t -= days * 86400;
                hours = Math.floor(t / 3600) % 24;
                t -= hours * 3600;
                minutes = Math.floor(t / 60) % 60;
                t -= minutes * 60;
                seconds = t % 60;
                return [days, hours, minutes, seconds];
            }
        };
    }
]);

HTML

<div class="col-xs-12" ng-repeat="event in events">
    <countdown date="{{ event.event_date }}"></countdown>
</div>

TEMPLATE

<div class='time_division_container'>
    <div class='digits_container'>{{ days }}</div>
    <div class='label_container'>DAYS</div>
</div>
<div class='time_division_container'>
    <div class='digits_container'>{{ hours }}</div>
    <div class='label_container'>HOURS</div>
</div>
<div class='time_division_container'>
    <div class='digits_container'>{{ minutes }}</div>
    <div class='label_container'>MINUTES</div>
</div>
<div class='time_division_container'>
    <div class='digits_container'>{{ seconds }}</div>
    <div class='label_container'>SECONDS</div>
</div>

This works fine at first if the countdown is only 1. But when I add multiple event_date in the event object the

$interval.cancel(stop);

seems not working.

For example if I have these event dates

var events = {
    {"event_date" : "2017-11-30 12:00:00"},
    {"event_date" : "2017-11-01 09:00:00"}
};

The first date is working fine but the second date which has already passed is not stopping its countdown. If you look at the console log it still displays "Should Stop" multiple times. It should only display once since I made and if statement that calls the "stopTimer" function when the difference of the current time and the event date is 0 or negative.

Please help. Thanks a lot.

Upvotes: 0

Views: 964

Answers (1)

james00794
james00794

Reputation: 1147

You have a scoping problem. stopTimer is being defined as a global variable, and each time the directive instantiates it overwrites the previous definition. So when you call stopTimer from the first directive, it calls the stopTimer defined in the second directive, who's stop variable is pointing to something else. Also, probably a typo in your question, but events should be an array for ng-repeat to work.

If you change:

  stopTimer = function () {
    console.log("Should Stop");
    $interval.cancel(stop);
  };

to

  var stopTimer = function () {
    console.log("Should Stop");
    $interval.cancel(stop);
  };

it works correctly, as stopTimer is now scoped. See the attached plunkr: https://plnkr.co/edit/41DlPAP07iBtmAq3kKbR

Aside, it's useful to enable strict mode to avoid scoping problems like this. See What does "use strict" do in JavaScript, and what is the reasoning behind it?. If strict mode were enabled, you would have seen an error in your console.

Upvotes: 1

Related Questions