Capturing the value of a child element using an Angular directive

When I include scope: {finishcallback: "&"} in my directive, the binding of values with $scope.minutes = 1 to ng-bind="minutes" stops working.

I am currently working on creating a countdown timer using Angular directives. However, I am facing issues in setting the value of remaining minutes and seconds to the child span element when I introduce a scope function in the directive.

<time id="countdown_{{order.Id}}" ng-if="order.StatusCode == 1" countdown="{{order.RemainingTimeToPrepareOrder}}" finishcallback="vm.countdownfinished(parameter)" callbackparameter="{{order.Id}}" countdownfinished="toggle()">                                        
  <b> <span class="value" ng-bind="minutes"></span> minutes   <span class="value" ng-bind="seconds">--</span> seconds</b>
</time>

Below is the code for my directive.

function countdown() {
    return {
        restrict: 'A', 
        scope: {
            finishcallback: "&"
        },
        controller: function ($scope, $attrs, $timeout) {

            $attrs.$observe('countdown', function (value) {
                var ds = new Date();
                ds.setTime(value * 1000);

                $scope.days = '-';
                $scope.hours = $scope.minutes = $scope.seconds = '--';

                $scope.timeout = $timeout(update, 1000);

                function update() {
                    now = +new Date();

                    $scope.delta = Math.round((ds - now) / 1000);
                    if ($scope.delta >= 0) {
                        $timeout(update, 1000);
                    } else if ($attrs.countdownfinished) {
                        $scope.$apply($attrs.countdownfinished);
                    }
                }
            });
        },
        link: function ($scope, $element, $attrs) {
            $scope.$watch('delta', function (delta) {
                if (typeof delta === 'undefined') return;

                if (delta < 0) {
                    delta = 0;
                }

                $scope.days = Math.floor(delta / 86400);
                $scope.hours = forceTwoDigits(Math.floor(delta / 3600) % 24);
                $scope.minutes = forceTwoDigits(Math.floor(delta / 60) % 60);
                $scope.seconds = forceTwoDigits(delta % 60);
            });
            $scope.toggle = function () {
                $scope.finishcallback({ parameter: $attrs.callbackparameter });
            }
            function forceTwoDigits(num) {
                return String(num < 10 ? '0' + num : num);
            }

        }
    }
}

Everything was functioning properly until I introduced the finishcallback: "&" scope variable in my directive to allow custom function calls upon countdown completion. After adding this, the assignments like $scope.minutes no longer update the values in my spans.

Is there a way to dynamically change the span values even after defining a scope in my directive?

Answer №1

If you're looking for a solution, my suggestion would be to utilize a pre-made template:

function countdown($timeout) {
  return {
    restrict: 'A',
    scope: {
      finishcallback: "&"
    },
    template: `<b> <span class="value" ng-bind="minutes"></span>  minutes   <span class="value" ng-bind="seconds">--</span> seconds</b>`,
    controller: function($scope, $attrs) {

      $attrs.$observe('countdown', function(value) {
        var ds = new Date();
        ds.setTime(value * 1000);

        $scope.days = '-';
        $scope.hours = $scope.minutes = $scope.seconds = '--';

        $scope.timeout = $timeout(update, 1000);

        function update() {
          now = +new Date();

          $scope.delta = Math.round((ds - now) / 1000);
          if ($scope.delta >= 0) {
            $timeout(update, 1000);
          } else if ($attrs.countdownfinished) {
            $scope.$apply($attrs.countdownfinished);
          }
        }
      });
    },
    link: function($scope, $element, $attrs) {
      $scope.$watch('delta', function(delta) {
        if (typeof delta === 'undefined') return;

        if (delta < 0) {
          delta = 0;
        }

        $scope.days = Math.floor(delta / 86400);
        $scope.hours = forceTwoDigits(Math.floor(delta / 3600) % 24);
        $scope.minutes = forceTwoDigits(Math.floor(delta / 60) % 60);
        $scope.seconds = forceTwoDigits(delta % 60);
      });
      $scope.toggle = function() {
        $scope.finishcallback({
          parameter: $attrs.callbackparameter
        });
      }

      function forceTwoDigits(num) {
        return String(num < 10 ? '0' + num : num);
      }

    }
  }
}

angular.module('app', [])
  .controller('ctrl', function($scope, $interval) {
    $scope.order = {
      Id: 1,
      StatusCode: 1,
      RemainingTimeToPrepareOrder: Date.now() + 5 * 60 * 1000,
    };
    $scope.countdownfinished = function(parameter) {
      console.log(parameter);
    }
    $scope.toggle = function() {
      console.log("Toggle");
    }

    $interval(function() {
      $scope.order.RemainingTimeToPrepareOrder -= 1000;
    }, 1000);
  })
  .directive('countdown', countdown);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <time id="countdown_{{order.Id}}" ng-if="order.StatusCode == 1" countdown="{{order.RemainingTimeToPrepareOrder}}" finishcallback="countdownfinished(parameter)" callbackparameter="{{order.Id}}" countdownfinished="toggle()"> 
</time>
</div>

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 process for translating symbols in a URL or text into hexadecimal characters? (e.g. changing = to %3D)

Currently, my script in use is extracting variables from URL parameters using jQuery. The value it retrieves happens to be a URL. For instance, if the URL is as follows: http://localhost/index.html?url=http://www.example.com/index.php?something=some the ...

Trigger function in React after the page finishes loading

I have a scenario where I need to display images onDrop within one of my components. To ensure a smooth drop experience, I am considering preloading the images using the following approach: componentDidMount(){ this.props.photos.forEach(picture => ...

Tips for passing parameters in a BootstrapDialog.show({ }) function popup

I am trying to display a popup using BootstrapDialog and pass a parameter with it. I have used the data attribute in my code snippet as shown below: BootstrapDialog.show({ closable: false, title: "This is my custom popup", message: $(' ...

Multer failing to generate file during request process

My current setup involves a router and multer middleware, but I'm facing an issue where the file requested is not being created. As a result, req.file always remains undefined. const multer = require('multer'); let storage = multe ...

What is the reason my answer for the powerset problem is flawed? Both my recursive and iterative methods are attached for review

How can I generate all possible subsets from an array of unique integers? For instance, if I have powerSet[1,2,3], the expected output should be [[], [1], [2], [3], [1,2], [1,3], [2,3], [1,2,3]] I've tried a recursive approach: function powerset(arr ...

Storing a variable in jQuery using AJAX and retrieving it at a later time

Hey there! I'm currently using jQuery and AJAX to fetch the user ID of the logged-in user. I'm storing this information in a variable so that I can use it for some logic later on. However, I'm facing issues with accessing it. Here's my ...

Loop through a set of data with a filter that applies to two specific

I'm trying to figure out how to use a single ng-repeat that filters based on either 'the order' or 'the id'. Here is an example of what I'm attempting: ng-repeat "cd in cds | filter: !order ? orderBy:'id' : orderBy ...

Display the keys of a nested array in Vue.js when the structure is unknown

Here is a representation of a dynamic array I have: nodes: [ { n1: "Foods", }, { n4: "Drinks", b7: [ { a2: "Beers", a4: [ ...

Which JavaScript library or template engine would be most suitable for this scenario?

I am tasked with creating an invite your Facebook friends module that will display the names and photos of your friends, allowing you to message them. It is essential that this feature seamlessly integrates into my website's design, so I need to style ...

How can Angular be used to fetch the name associated with a user_id in Laravel?

There seems to be a problem with fetching the name attribute along with the title and body attributes. The name appears empty on page refresh but shows up automatically upon submission. Interestingly, angularjs is unable to retrieve the name successfully. ...

Using Jquery to create an array containing all the items in the pager

192.168.1.1/home?page=1, 192.168.1.1/home?page=2, 192.168.1.1/home?page=3. Is there a way to create an array of only the new items on the pager? I am interested in storing only the elements with the class item-new into the array. To clarify further: I n ...

Unable to receive notifications within an AngularJS service

<!DOCTYPE html> <html> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script> <body> <div ng-app="canerApp" ng-controller="canerCtrl"> <button ng-click="click()"> ...

Add an event to your Fullcalendar with a date that is not the same as the present date in your MySQL database

I currently have Fullcalendar set up to display events from a MySQL table (title + datetime) and allow users to add new events by clicking on a specific day within the calendar. However, I am facing an issue where it only adds events to the current day ev ...

Transforming JQuery code into pure Javascript: Attaching an event listener to dynamically generated elements

After exhausting all available resources on stack overflow, I am still unable to find a solution to my problem. I am currently trying to convert the JQuery function below into Vanilla JavaScript as part of my mission to make web pages free of JQuery. How ...

Creating dynamic routes in react-router-dom using conditions

I'm currently developing an application using react-router-dom for navigation. I've encapsulated all my <Routes> inside a container provided by Material UI. However, I want my home page to be outside of this container so that I can display ...

Steps for eliminating an element using jQuery from a variable filled with HTML code

I'm developing a forum where users have the ability to quote other users' comments. When a user clicks on "quote" for a comment, it captures the HTML of that comment and displays it in a box that says Quote: Original post by a member, similar t ...

jQuery's visibility check function is not functioning properly

I am developing a web application for managing orders and finance in a restaurant. To enhance the functionality of my application, I require more screens to operate with. To facilitate this, I have implemented a small function to toggle between visibility: ...

Scanning through a directory to find fragments of a file's title

Currently, I am in the process of creating a media viewing platform that automatically downloads new episodes of TV shows. One obstacle I have encountered is the need to specify a source for the video content, as each episode download has a unique naming ...

Display all items that contain a specified string using JavaScript

I'm in need of some assistance with a problem that I've been struggling with. I have several JavaScript objects containing different data pieces as shown below:- Object {id: 1, shopcounty: "cornwall", shopaddress: "the cycle centre,<br />1 ...

Issues with AngularJS ng-repeat functionality

Hey there! I'm encountering an issue with accessing data from a table using ng-repeat in my code. Even though everything seems correct, the data doesn't load when I view the page. Here's a snippet of my table setup: <table class="table t ...