ZeroThe2nd ZeroThe2nd - 10 months ago 71
AngularJS Question

AngularJS simple clock component

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

, but
instead, I wrote my component as follows:

.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">{{ $ }}</span>:' +
'<span id="clock-seconds">{{ $ }}</span>' +
controller: function ClockController($interval){
this.hh = = = null;

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

Now, this all works perfectly fine, besides the fact that neither
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
style, and are using
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

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

Answer Source

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 = = = null;

  this.clock = function() {

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