0

I have a directive but I am facing problem in watching an attribute from the directive controller.

    angular.module('app',[])
.directive('timer1', function () {
    return {
        template: '<div class="timerCont1"><div class="progressBar"></div></div>',
        restrict: 'E',
        replace:true,
        scope: true,
        controller: function ($scope, $element, $attrs) {
            $scope.$watch($attrs.timerevent, function (value) {
                switch ($attrs.timerevent)
                {
                    case "start":
                        $scope.timeoutId = null;
                        $scope.countdown = Number($attrs.timer);
                        $scope.tick();
                        break;
                    case "stop":
                        $scope.stop();
                        break;
                    case "destroy":
                      alert()
                        $scope.stop();
                        $scope.$emit('destroy_pizza', {

                            });

                }

            },true);
            $scope.tick = function () {
                $scope.timeoutId = setTimeout(function () {
                    if ($scope.countdown <= 0) {
                        $scope.$apply(function () {
                            $attrs.$set('timerevent', 'destroy')
                        });
                    }
                    else {
                        $scope.countdown--;

                        $scope.tick();
                    }
                    $scope.$apply();
                }, $attrs.interval);
            };

           $scope.stop =  function () {
                   clearTimeout($scope.timeoutId);
                   $scope.timeoutId = null;

           };

        }
    };
});  

And here goes my hTML

<timer1 interval="1000" timerevent="start" timer="10"></timer1>

When I am setting the attribute timerevent to "destroy" my watch is not getting called, whereas the attribute is updated successfully.

infinityskyline
  • 369
  • 2
  • 4
  • 17
  • Why are you using an attribute to control the timer component instead of a scope variable? I can write an answer to solve your problem, but the whole approach to the design of this component seems unwise. For more information see, [AngularJS Developer Guide - Component-based Application Architecture](https://docs.angularjs.org/guide/component#component-based-application-architecture). – georgeawg Nov 27 '17 at 19:55
  • Also `replace=true` is deprecated. For more information, see [Why is replace deprecated in AngularJS?](https://stackoverflow.com/questions/24194972/why-is-replace-deprecated-in-angularjs/35545445#35545445). – georgeawg Nov 27 '17 at 19:57
  • @georgeawg You seemed to have forgot to include the jquery plugin. Here is the working plunker https://plnkr.co/edit/ZYLsDNmH4sYMn2N45dot – infinityskyline Nov 28 '17 at 05:14

2 Answers2

0

If you are going to get changes in $watch use the scope instead of $attrs.

angular.module('abc').directive('timer1', function () {
    return {
        template: '<div class="timerCont1"><div class="progressBar"></div></div>',
        restrict: 'E',
        replace:true,
        scope: {
            timerevent:"=",
            timer:"@",
            interval:"@"
        },
        controller: function (scope, $element, $attrs) {
           scope.$watch('timerevent', function () {
              //this section will be run after chnaging the timerevent  
           },true);
        }
    };
}); 
Iman Bahrampour
  • 6,180
  • 2
  • 41
  • 64
  • `replace=true` is deprecated. For more information, see [Why is replace deprecated in AngularJS?](https://stackoverflow.com/questions/24194972/why-is-replace-deprecated-in-angularjs/35545445#35545445). – georgeawg Nov 27 '17 at 21:08
  • @georgeawg. the replace property does not destroy its functionality. what do you do if you are going to delete a directive element from an HTML? – Iman Bahrampour Nov 27 '17 at 21:20
  • It's deprecated because there are known, very silly problems with `replace: true`, a number of which can't really be fixed in a reasonable fashion. If you're careful and avoid these problems, then more power to you, but for the benefit of new users, it's easier to just tell them "this will give you a headache, don't do it". – georgeawg Nov 27 '17 at 21:24
  • @georgeawg. I got your mean dude. – Iman Bahrampour Nov 27 '17 at 21:36
  • I am very thankful for all your answers.. but unfortunately I have to watch the attrs. So can you please set a working code where attr can be watched from controller. Here is my code https://plnkr.co/edit/ZYLsDNmH4sYMn2N45dot – infinityskyline Nov 28 '17 at 05:17
0

I managed to get a solution to my own problem :) Instead of watch I tried observing the attribute Here is my working code https://plnkr.co/edit/LKuYcCU5z5wa7dTe1Uzo

Since its a long piece of code I am writing my controller

<timer1 interval="1000" timer-event="start" timer="10"></timer1>
$attrs.$observe('timerEvent', function(value) {
        switch (value.toLowerCase()) {
          case "start":
            $scope.timeoutId = null;
            $scope.countdown = Number($attrs.timer);
            $scope.tick();
            break;
          case "stop":
            $scope.stop();
            break;
          case "destroy":
            alert("It is watched")
            $scope.stop();
            $scope.$emit('destroy_pizza', {

            });

        }

      }, true);

For more information, see AngularJS $compile Attributes API Reference - $observe.

georgeawg
  • 48,608
  • 13
  • 72
  • 95
infinityskyline
  • 369
  • 2
  • 4
  • 17