1

As I'm currently trying to make a smart mirror system based on angularJS, I started making a clock component as basic. Having done a bit of angular before, but not using component structure, I decided to give that a shot.

The angularJS component tutorial quickly learned me to not use $scope, but this instead, I wrote my component as follows:

angular
    .module('smartMirrorFrontend', [])
    .component('clock', {
        template:   '<div class="iface-component" id="component-clock">' +
                        '<h1>Clock component Angular</h1>' +
                        '<span id="clock-hours" >{{ $ctrl.hh }}</span>:' +
                        '<span id="clock-minutes">{{ $ctrl.mm }}</span>:' +
                        '<span id="clock-seconds">{{ $ctrl.ss }}</span>' +
                    '</div>',
        controller: function ClockController($interval){
            this.hh = this.mm = this.ss = null;

            this.clock = function (){
                const d = new Date();
                this.hh = ('0' + d.getHours()).slice(-2);
                this.mm = ('0' + d.getMinutes()).slice(-2);
                this.ss = ('0' + d.getSeconds()).slice(-2);
            };
            this.clock();
            $interval(this.clock, 1000);
        }
    });

Now, this all works perfectly fine, besides the fact that neither $interval nor $timeout seem to be able to fire my function every second.

Here's the small catch: I have checked out other AngularJS clock questions on stackoverflow, but none implement it in the this style, and are using $scope instead. They also just place the values in one span, while I need this clock to be able to stand in vertical mode (so top to bottom) in separate spans (as seen in the template part)

The console in the webbrowser is not showing any problems, the component displays and loads the time once and correctly, meaning the function does fire once as it should. The component is inserted in the html using <clock></clock>

My question being: Why is my interval not working as it should be, and how can I make it work?

2 Answers 2

2

The issue here is not with $interval but with the localized scoping of this.

this is a unique identifier in JavaScript, that is scoped to the particular function that calls it. In the code presented here, this is pointing to the clock() function, not the ClockController function when the $interval is executed.

There are two ways to fix this issue; one simplistic method would be to create an alias to this so that it can be referenced inside the callback. The other method would be to use .bind(). I will demonstrate the alias method here:

controller: function ClockController($interval) {
  var comp = this;
  this.hh = this.mm = this.ss = null;

  this.clock = function() {

    const d = new Date();
    comp.hh = ('0' + d.getHours()).slice(-2);
    comp.mm = ('0' + d.getMinutes()).slice(-2);
    comp.ss = ('0' + d.getSeconds()).slice(-2);
    console.log(comp);
  };
  this.clock();
  $interval(this.clock, 1000);
}

http://plnkr.co/edit/NFmP29re497d5kyJnqNP?p=preview

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

1 Comment

Thanks, this actually helped solving the issue AND taught me something about the scope of the this identifier.
1

At the start of your directive you can assign this to a variable:

var self = this;

This allows you to know that self refers to the directive. This is useful when you are using this inside of other functions.

you need to set a timeout inside of your clock function, so that it keeps calling it's self

self.clock = function (){
    var d = new Date();
    self.hh = ('0' + d.getHours()).slice(-2);
    self.mm = ('0' + d.getMinutes()).slice(-2);
    self.ss = ('0' + d.getSeconds()).slice(-2);
    this.time = new Date();
    $timeout(self.clock,new Date().getTime() % 1000);
};

This timeout is set to call the function on the next second.

2 Comments

Because I need to be abel to grab the values in separate spans to style and position them in the way I need to. At the same time, this still doesn't solve the problem where the clock only updates on page load.
@ZeroThe2nd sorry about that changed my answer to address that

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.