0

I have a small script with a countdown, created through a directive, which starts if a $scope value inside the controller is true. This is the html code:

<countdown from="3" start-if="{{startCountdown}}"></countdown>

Followed by the code of the directive:

app.directive('countdown', function ($interval) {
  return {
    restrict: 'E',
    template: '{{count}}',
    controller: function($scope, $element, $attrs) {
      $scope.count = $attrs.from;

      function countdown(){
        var intervalID = $interval(function() {
          if ($scope.count > 0) {
            $scope.count--;
          } else {
            $interval.cancel(intervalID);
          }
        }, 1000);
      }

      $attrs.$observe('startIf', function(value) {
        if (value) {
          countdown();
        }
      });
    }
  }
});

The countdown is working properly but inside the controller, if $scope.count === 0, there should be an alert() but it is not working.

This is a Plnkr with the complete code. Do you know how to pass the value of $scope.count to the controller and solve this issue? Thanks in advance for your replies!

1
  • It looks like you are using the parent scope in this directive, i.e. not isolated scope for the directive because you have no scope: {...} in your directive code above. Which means that you should be able to simply just put a $scope.$watch('count', ...) in the controller to watch for the change to the scope variable. If you want to use isolated scope then you could put a method binding scope: { countdown: '&' } in your directive and then you can setup a binding to in the controller to that method and then call that method from your directive. Commented Sep 19, 2016 at 12:54

2 Answers 2

2

I. Child scope directive.

You did not created isolated scope, so easiest solution is to remove from attribute and init count scope variable in controller. So:

//controller code
//init variable
$scope.count=3;

//directive code
//manipulate variable
$scope.count--;

Example with directive without isolated scope ( child scope ):

var app=angular.module("app",[]);
app.controller("controller",function($scope,$timeout){

   $scope.count=2;
   $scope.start=false;//start countdown flag


   $scope.$watch("count",function(val){
   
     console.log("Count is changed to:"+val);
     
   });
  
});

app.directive("myDirective",function($timeout){

   return{
     restrict:"E",
     template:"{{count}}",
     link:function(scope){
     
       scope.count++;//example change
  
       $timeout(function() { scope.count++; },2000);//example change

       scope.$watch("start",function(){
         
            //here we watch changes in start scope variable
            //here start countdown

       });
       
     }
   }
   
  
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="controller">
  <my-directive></my-directive>
</div>  

II. Isolated scope directive

You can also do the same thing with isolated scope, it need to pass variable by = ( two way binding ). Example:

    var app=angular.module("app",[]);
    app.controller("controller",function($scope){

       $scope.count=2;
      
       $scope.$watch("count",function(val){
       
         console.log("Count is changed to:"+val);
         
       });
      
    });

    app.directive("myDirective",function($timeout){

       return{
         restrict:"E",
         scope:{
         count:"="//pass variable to isolated scope
         },
         template:"{{count}}",
         link:function(scope){
         
           scope.count++;//example change
      
           $timeout(function() { scope.count++; },2000);//example change
           
         }
       }
       
      
    });
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="app" ng-controller="controller">
      <my-directive count="count" ></my-directive>
    </div>  

Sign up to request clarification or add additional context in comments.

3 Comments

Your solution seems reasonable, but can you edit the file by also modifying the start-if attribute applied to the directive?
@d_z90 i added in first code example variable start. So create variable in controller then watch it in directive, in callback You can run countdown.
is the poster not asking how to pass the var from the directive to controller? This show the opposite ie: from controller to directive.
1

You can use $broadcast to achieve this with same code.

controller: function($scope, $element, $attrs, $rootScope) {
  $scope.count = $attrs.from;

  function countdown(){
    var intervalID = $interval(function() {
      $rootScope.$broadcast('counterVal',{
          countVal:$scope.count
        });
      if ($scope.count > 0) {
        $scope.count--;

      } else {
        $interval.cancel(intervalID);
      }
    }, 1000);
  }

  $attrs.$observe('startIf', function(value) {
    if (value) {
      countdown();
    }
  });
}

Please find the working plunker here.

1 Comment

Maciej solution is correct too, but this is better since it uses the scope as isolated. Thanks man!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.