Привязка значения дочернего элемента из директивы Angular

Привязка значений с $scope.minutes = 1 к ng-bind="minutes" не работает, когда я добавляю scope: {finishcallback: "&"}, в свою директиву.

Я пытаюсь реализовать таймер обратного отсчета с директивами Angular, но не могу установить значение оставшейся минуты и секунды для дочернего элемента span, когда я определяю функцию области действия в директиве.

<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>  dakika   <span class="value" ng-bind="seconds">--</span> saniye</b>
</time>

И вот мой код директивы.

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);
            }

        }
    }
}

Все функции работают, пока я не добавлю переменную области видимости finishcallback: "&" в свою директиву. Я добавил это, чтобы включить вызовы пользовательских функций после завершения обратного отсчета. Но когда я добавляю это, мои назначения, такие как $scope.minutes, перестали изменять значения в моих промежутках.

Как мне динамически изменять значения диапазона, даже если я определяю область действия в своей директиве?


person Yusuf Duyar    schedule 13.10.2020    source источник
comment
неправильный тег .. пожалуйста, измените angular на angularjs :)   -  person Tony    schedule 13.10.2020
comment
Это потому, что вы забыли кавычки вокруг {{order.RemainingTimeToPrepareOrder}}?   -  person Ruben Helsloot    schedule 13.10.2020
comment
Неа. Это не проблема. моя главная проблема в том, что ng-bind="minutes" не работает, когда я добавляю scope: { finishcallback: "&" }, в свою директиву. @РубенХелслот   -  person Yusuf Duyar    schedule 13.10.2020


Ответы (1)


Я бы рекомендовал просто использовать шаблон:

function countdown($timeout) {
  return {
    restrict: 'A',
    scope: {
      finishcallback: "&"
    },
    template: `<b> <span class="value" ng-bind="minutes"></span>  dakika   <span class="value" ng-bind="seconds">--</span> saniye</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>

person Ruben Helsloot    schedule 13.10.2020