Angularjs 更改指令中的控制器范围变量不会反映在控制器函数中

Angularjs 更改指令中的控制器范围变量不会反映在控制器函数中,angularjs,angularjs-directive,Angularjs,Angularjs Directive,在我的指令中,我有一个控制器变量,当您按下指令中的按钮时,该页将递增。但是,调用控制器函数的下一行,scope.alertPage()没有反映此更改。请注意,当您单击按钮时,页面仍会被警告为1 我知道我可以通过在控制器中添加$scope.$apply来解决这个问题,但随后我得到一个错误,即已经发生了摘要 app=angular.module('app',[]); 应用程序控制器('myCtrl',函数($scope){ $scope.page=1; $scope.alertPage=函数(){

在我的指令中,我有一个控制器变量,当您按下指令中的按钮时,该页将递增。但是,调用控制器函数的下一行,
scope.alertPage()
没有反映此更改。请注意,当您单击按钮时,页面仍会被警告为1

我知道我可以通过在控制器中添加$scope.$apply来解决这个问题,但随后我得到一个错误,即已经发生了摘要

app=angular.module('app',[]);
应用程序控制器('myCtrl',函数($scope){
$scope.page=1;
$scope.alertPage=函数(){
警报($scope.page);
}
})
app.directive('incrementer',function(){
返回{
范围:{
页码:'=',
alertPage:“&”
},
模板:“增量页”,
链接:功能(范围、要素、属性){
scope.incrementPage=函数(){
scope.page+=1;
scope.alertPage();
}
}
}
})
html模板:

  <body ng-app='app' ng-controller='myCtrl'>
    page is {{page}}

    <incrementer page='page' alert-page='alertPage()'></incrementer>
  </body>

页面为{{page}

尝试以稍微不同的方式执行此操作。传入函数以在指令内部执行递增而不是递增

HTML

指导

         scope: {
           page: '&',      // Receive like this
           alertPage: '&'
         },


          link: function(scope, elem, attrs) {
               scope.incrementPage = function() {
                 scope.page();          // Call as function
                 scope.alertPage();
               }  
          }

它没有立即显示更新的值的原因是,双向绑定仅在摘要循环期间更新父级(或指令的使用者范围)范围的绑定值。摘要循环发生在ng点击被触发之后。因此,控制器中的
$scope.page
尚未更新。您可以通过使用
timeout
以多种方式绕过此问题,它将延迟在摘要周期结束时运行的操作。您还可以通过将一个对象设置为双向绑定属性来保存该值。由于双向绑定属性和父范围共享同一个对象引用,您将立即看到更改

方法1-使用超时:

  scope.incrementPage = function() {
     scope.page += 1;
     $timeout(scope.alertPage)
  }  
 //In your controller
 $scope.page2 = {value:1};

//In your directive 
scope.incrementPage = function() {
     scope.page.value += 1;
     scope.alertPage();
 }  
//In your controller
$scope.alertPage = function(val) {
  alert(val);
}
方法2-绑定对象:

  scope.incrementPage = function() {
     scope.page += 1;
     $timeout(scope.alertPage)
  }  
 //In your controller
 $scope.page2 = {value:1};

//In your directive 
scope.incrementPage = function() {
     scope.page.value += 1;
     scope.alertPage();
 }  
//In your controller
$scope.alertPage = function(val) {
  alert(val);
}
Method3-使用带参数的函数绑定传递值:

  scope.incrementPage = function() {
     scope.page += 1;
     $timeout(scope.alertPage)
  }  
 //In your controller
 $scope.page2 = {value:1};

//In your directive 
scope.incrementPage = function() {
     scope.page.value += 1;
     scope.alertPage();
 }  
//In your controller
$scope.alertPage = function(val) {
  alert(val);
}

app=angular.module('app',[]);
应用程序控制器('myCtrl',函数($scope){
$scope.page=1;
$scope.page2={value:1};
$scope.alertPage=函数(){
警报($scope.page);
}
$scope.alertPage2=函数(){
警报($scope.page2.value);
}
})
app.directive('incrementer',函数($timeout){
返回{
范围:{
页码:'=',
alertPage:“&”,
第2页:“=”,
alertPage2:“&”
},
模板:“增量页”,
链接:功能(范围、要素、属性){
scope.incrementPage=函数(){
scope.page+=1;
scope.page2.value+=1;
$timeout(函数(){scope.alertPage()});
scope.alertPage2();
}
}
}
})

您可以通过引用传递变量,然后更新将立即进行(因为您不会复制它,而只是传递它在内存中的位置)

视图:


问题是时间线关闭了

  • 单击按钮,递增页面()
  • 指令范围值增加(现在为2)
  • alertPage()父作用域值已读取(仍为1)
  • 父范围作为摘要的一部分更新(现在为2)
  • 要解决此问题,您需要在摘要周期后调用警报函数(例如,
    $timeout
    ),或者需要观察父范围中的更改

    // in controller
    $scope.$watch('page', function (currentValue, previousValue) {
      // initially triggered with same value
      if (currentValue > previousValue) {
        alert(currentValue)
      }
    })
    
    然后自然更改值

    // in directive html
    <button ng-click="page = page + 1">
    
    //在指令html中
    
    将其置于$timeout或绑定到具有该属性的对象。由于是双向绑定,因此只有在下一个摘要周期中才会更新原始的双向绑定值。i、 e尝试
    $timeout(scope.alertPage)
    或者您可以在控制器集
    $scope.page={value:1}
    和指令do
    $scope.page+=1中尝试的其他方法和rest无论你在做什么,真的要为此创建一个手表吗?函数绑定的目的在这里完全失去了。我确信粘贴到递增数字的示例仅仅是一个示例,原始代码必须比这个更复杂。@PSL我认为$watch是一个优雅的解决方案。使用$timeout会触发一个全新的摘要周期afaik。在这种情况下并非如此,ngclick timeout将有一个摘要周期,它将自己添加到asyc队列中,该队列将与相同的摘要周期一起运行。。此外,你不应该只是制作手表。。在这种情况下,它实际上是不必要的,并且会累积到摘要循环中。是的,与我的示例中的方法2类似。。思想相似。。干杯……)
    
    // in directive html
    <button ng-click="page = page + 1">