更改指令中的控制器范围变量不会反映在控制器功能中

时间:2014-12-17 19:07:11

标签: angularjs angularjs-directive

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

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

Plunker

app = angular.module('app', []);

app.controller('myCtrl', function($scope) {

  $scope.page = 1;

  $scope.alertPage = function() {
    alert($scope.page);
  }

})

app.directive('incrementer', function() {
  return {
    scope: {
      page: '=',
      alertPage: '&'
    },
    template: '<button ng-click="incrementPage()">increment page</button>',

    link: function(scope, elem, attrs) {
      scope.incrementPage = function() {
          scope.page += 1;
          scope.alertPage();
      }
    }
  }
})

html模板:

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

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

4 个答案:

答案 0 :(得分:7)

它没有立即显示更新值的原因是因为双向绑定仅在摘要周期期间更新父级(或指令的使用者范围)范围的绑定值。触发ng-click后会发生摘要循环。因此控制器中的$scope.page尚未更新。您可以通过使用timeout以多种方式解决此问题, scope.incrementPage = function() { scope.page += 1; $timeout(scope.alertPage) } 会将操作推迟到摘要周期结束时运行。您也可以通过设置一个将值保存为双向绑定属性的对象来完成此操作。由于双向绑定属性和父作用域共享相同的对象引用,因此您将立即看到更改。

方法1 - 使用超时:

 //In your controller
 $scope.page2 = {value:1};

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

方法2 - 绑定对象:

//In your controller
$scope.alertPage = function(val) {
  alert(val);
}

Method3 - 使用带参数的函数绑定传递值:

<!--In the view-->
<div incrementer page="page" alert-page="alertPage(page)"></div>

//In the directive
scope.incrementPage = function() {
     scope.page += 1;
     scope.alertPage({page:scope.page});
 }  

app = angular.module('app', []);

app.controller('myCtrl', function($scope) {

  $scope.page = 1;
  $scope.page2 = {value:1};
  
  $scope.alertPage = function() {
    alert($scope.page);
  }
  
  $scope.alertPage2 = function() {
    alert($scope.page2.value);
  }

})

app.directive('incrementer', function($timeout) {
  return {
   
    scope: {
      page: '=',
      alertPage: '&',
      page2:"=",
      alertPage2: '&'
    },
    template: '<button ng-click="incrementPage()">increment page</button>',

    link: function(scope, elem, attrs) {
      scope.incrementPage = function() {
          scope.page += 1;
          scope.page2.value += 1;
          $timeout(function(){ scope.alertPage() });
          scope.alertPage2();
      }
    }
  }
})

&#13;
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
  <div incrementer page="page" alert-page="alertPage()" page2="page2" alert-page2="alertPage2()"></div>
  </div>
&#13;
{{1}}
&#13;
&#13;
&#13;

答案 1 :(得分:2)

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

查看:

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

指令:

link: function(scope, elem, attrs) {
  scope.incrementPage = function() {
      scope.page.page += 1;
      scope.alertPage();
  }

答案 2 :(得分:1)

问题是时间表已关闭。

    单击
  1. 按钮,incrementPage()
  2. 指令范围值递增(现在为2)
  3. alertPage()父范围值读取(仍为1)
  4. 父作用域更新为摘要(现在为2)
  5. 的一部分

    要解决此问题,您需要在摘要周期后调用提醒功能(例如$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">
    

答案 3 :(得分:0)

尝试稍微改变一下。传递函数来执行增量而不是在指令

内递增

HTML

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

控制器

          $scope.incPage = function() {    // Function to increment
             $scope.page++;
         };

指令

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


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