将范围值从指令传递到控制器 - AngularJS

问题描述:

我有一个带有倒计时的小脚本,通过directive创建,如果controller中的$scope值为true,则该脚本开始。这是html代码:将范围值从指令传递到控制器 - AngularJS

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

其次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(); 
     } 
     }); 
    } 
    } 
}); 

倒计时工作正常,但controller内,如果$scope.count === 0,应该有一个alert()但它不是加工。

这是一个Plnkr与完整的代码。您知道如何将$scope.count的值传递给controller并解决此问题吗?提前感谢您的回复!

+0

它看起来像你使用这个指令父范围,即不隔离指令范围,因为你没有范围:{...}在你的指令上面的代码。这意味着你应该能够简单地在控制器中放置一个$ scope。$ watch('count',...)来监视范围变量的变化。如果你想使用独立的范围,那么你可以在你的指令中放置一个方法绑定范围:{countdown:'&'},然后你可以在控制器中为该方法设置一个绑定,然后从你的指令中调用该方法。 –

您可以使用$广播用相同的代码来实现这一目标。

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

请找工作plunker here.

+0

Maciej的解决方案也是正确的,但这是更好的,因为它使用'范围'作为孤立的。谢啦! –

I.子范围指令。

您没有创建隔离范围,因此最简单的解决方案是删除控制器中的from属性和init count范围变量。所以:

与没有隔离的范围(子作用域)指令
//controller code 
//init variable 
$scope.count=3; 

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

实施例:

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。隔离范围指令

你也可以做同样的事情用隔离范围,它需要通过=(双向绑定)传递变量。例如:

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>

+0

你的解决方案看起来很合理,但你可以通过修改应用于该指令的'start-if'属性来编辑该文件吗? –

+0

@ d_z90我在第一个代码示例变量start中加入。因此,在控制器中创建变量,然后在指令中观察它,在回调中您可以运行倒计时。 –