The problem arises when Angular's $interval function is not recognized

Despite the possibility of this being considered a duplicate, none of the related topics have provided a solution to my simple date count down directive:

class Clock {
    constructor() {
        this.restrict = 'AC';
        this.replace = true;
        this.template = require('./templates/clock.tpl.html');
        this.scope = {};
    }
    link(scope, elem, attrs, $interval) {
        let end = new Date('05/05/2017 9:00 AM');

        let _second = 1000;
        let _minute = _second * 60;
        let _hour = _minute * 60;
        let _day = _hour * 24;

        scope.showRemaining = () => {
            let now = new Date();
            let distance = end - now;
            let days = Math.floor(distance / _day);
            let hours = Math.floor((distance % _day) / _hour);
            let minutes = Math.floor((distance % _hour) / _minute);
            let seconds = Math.floor((distance % _minute) / _second);

            scope.days = days;
            scope.hours = hours;
            scope.minutes = minutes;
            scope.seconds = seconds;
        }

        $interval(showRemaining, 1000;)
    }
}

// create factory function to handle DI
function factory() {
    "ngInject";

    return new Clock();
}

export default factory;

I've been searching for a solution to this issue and everywhere I find information stating that the interval function must be passed as a normal one without parameters or any additional features. However, I continue to encounter the same error message:

TypeError: $interval is not a function

Can someone provide assistance?

Answer №1

Injecting dependencies should be done in the constructor, not in the link function:

constructor($interval) {
    // ..
    this.$interval = $interval;
}
link(scope, elem, attrs) {
    // ..
    this.$interval(showRemaining, 1000;)
}

Answer №2

One issue with using classes to create directive objects is that directive functions have a non-lexical this, as explained in this particular answer. While it's possible to inject $interval into the constructor, utilizing it within the link function requires binding:

constructor($interval) {
  ...
  this.$interval = $interval;
  this.link = this.link.bind(this);
}

This reveals a flaw in the design. Directives and classes aren't an ideal match. The use of classes for constructing directive objects lacks advantages and reusability. It doesn't offer any architectural benefits.

Angular 1.5+ has borrowed concepts from Angular 2 to facilitate easier migration, steering development towards being controller-centric. As a result, pre-link and post-link functions have been replaced by hooks like $onInit and $postLink.

An effective approach to class-based AngularJS development could involve:

class ClockController {
  constructor($interval) {
    this.$interval = $interval;
  }

  $onInit() {
    this.$interval(() => this.showRemaining(), 1000);
  }

  showRemaining() { ... }
}

app.directive('clock', () => ({
  ...
  controller: ClockController
}));

At this stage, converting this directive into a component would be logical, considering that components essentially function as wrappers for directives, promoting a controller-centric approach.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the recursive process for printing the numbers 1 to 5 and then 5 to 1?

I was looking to print numbers from 5 to 0 and then from 0 to 5 in the most concise way possible. The code I came up with is below. However, I am open to other suggestions that may require fewer lines of code. Looking forward to your feedback. Thanks! ...

Learn how to save user input from form fields and text areas into JSON format using Angular

Is there a way to add comments using Angular when a user clicks on a button? Currently, whenever text is entered in the input field or textarea, it disappears and an empty block without any name, country, and comments is displayed. The entered text should ...

Using Ajax to send data to a PHP script

I am interested in implementing an AJAX call to a PHP script each time a specific button is clicked. The buttons correspond to different directions - right, left, top, and bottom, represented by divs named r, l, t, and b. I have attempted the code below ...

Utilizing the JSON.parse method in JavaScript in conjunction with an Ajax request while incorporating the escape character "\n" for new line functionality

https://jsbin.com/zuhatujoqo/1/edit?js,console Edit: json file has this line: {"pd":"ciao \\n ste"} I need to retrieve a valid JSON file through an ajax call. Then parse the result using JSON.parse. I'm confused about the behavior of t ...

Having difficulty resolving all parameters for the component: (?, [object Object]) in the Jasmine component Unit Test

While defining a UT for a component with an extended class using i8nService and ChangeDetectionRef, I encountered an error preventing me from instantiating it: Failed: Can't resolve all parameters for BrandingMultiselectComponent: (?, [object Object] ...

Is it possible to have an object nested within a function? How about a function within a function? I'm determined to grasp

0 Can someone explain to me how the function express() works? I'm having trouble understanding how you can call a function when stored in a variable like const app = express(); Then calling a function like listen() as if it were an object: app.list ...

What is the most effective method to convert PHP data into JSON and present it in the jQuery success scenario?

In the realm of jQuery, I have this particular piece of code: <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script> <script type="text/javascript" > $(function() { $("input[type ...

Avoid activating automatic save feature in Material UI data grid

After creating a data-grid and attempting to add records, I encountered an issue where pressing the TAB key automatically saved the data when focusing on the save button without manually pressing enter. How can this behavior be prevented so that manual con ...

What is the best way to send a JSON response from a Symfony2 controller?

I am utilizing jQuery to modify my form, which is created using Symfony. The form is displayed within a jQuery dialog and then submitted. Data is successfully stored in the database. However, I am unsure if I need to send some JSON back to jQuery. I am ...

What is the optimal order for executing JavaScript, jQuery, CSS, and other controls to render an HTML page efficiently?

What are some recommended strategies for optimizing webpage loading speed? What key factors should be taken into consideration? ...

Sort by label using the pipe operator in RxJS with Angular

I have a situation where I am using an observable in my HTML code with the async pipe. I want to sort the observable by the 'label' property, but I'm not sure how to correctly implement this sorting logic within the pipe. The labels can be e ...

Most effective method to verify if mutation observer meets specific criteria

I have set up a mutation observer to monitor changes in the page load. Specifically, I am interested in detecting the moment when a particular element is loaded or exists. This element can be identified by its classname, let's say it's called foo ...

Tips for utilizing Async/Await within an expressjs router

Having trouble with Async/Await in my Nodejs project. I'm a beginner with Nodejs and facing an issue connecting to my mongodb collection through my repository. When I integrate my controller with the repository, I end up getting a null response. Take ...

Processing ajax requests in Rails 4 using HTML format

I'm currently in the process of setting up ajax functionality for my contact form and I am currently testing to ensure that the ajax call is being made. When checking my console, I noticed that it is still being processed as HTML and I cannot seem to ...

Having difficulty receiving a response from an AJAX call within the success function

After browsing through this stack link Ajax response not calling success:function() when using jQuery 1.8.3, I'm puzzled as to why the success function is not invoked when I uncomment the dataType line. It seems that setting dataType = JSON prevents t ...

Discover a simple method for comparing JSON responses and UI elements by utilizing two arrays in a for loop within your Cypress automation tests

I am in need of assistance where I must compare JSON response data with UI elements. If matching elements are found, the task is to print them in a log file. This requires checking all JSON responses using a for loop. Can someone provide me with Cypress Ja ...

Counting down in JavaScript until the desired MySQL datetime format is reached

I'm trying to display a countdown of hours and minutes to a date pulled from a MySQL database in the format 2010-09-24 11:30:12. I am not well-versed with dates in JavaScript, so any guidance would be greatly appreciated. Thank you. ...

Tips for maintaining the menu state following a refresh

Is there a way to save the menu state when pressing F5? I'm looking for a similar functionality as seen on the Binance website. For example, clicking on the Sell NFT's submenu and then refreshing the page with F5 should maintain the menu state on ...

The intl-tel-input dropdown feature is malfunctioning on mobile browsers

Currently, I have integrated the intl-tel-input library into my project for selecting international telephone numbers from a dropdown menu. While accessing the application on a web browser, the country flags display correctly with the intended styling. Ho ...

How can I make sure addEventListener only responds to numbers and not images?

Currently, I am facing a dilemma with implementing a button that features an image on it and needs to be placed within another div. Despite successfully achieving this, I am struggling to comprehend the JavaScript code outlined in a tutorial I followed. Th ...