改变指令的控制器范围的变量并没有反映在控制器的功能 [英] changing a controller scope variable in a directive is not reflected in controller function

查看:149
本文介绍了改变指令的控制器范围的变量并没有反映在控制器的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的指导,我有一个控制器的变量,网页,当你preSS该指令的按钮,就会增。但是,下一行, scope.alertPage()它调用控制器功能并不反映这种变化。请注意,当您单击按钮页面仍然惊动为1!

我知道我可以通过添加$范围内解决这个问题。在控制器$申请,然后我得到,说摘要已经发生的错误。

Plunker: http://plnkr.co/edit/QSnBzM3gvJI9vnCkC19T?p=preVIEW

 应用程序= angular.module('应用',[]);app.controller('myCtrl',函数($范围){  $ scope.page = 1;  $ scope.alertPage =功能(){
    警报($ scope.page);
  }})app.directive('增量',函数(){
  返回{
    范围: {
      页:'=',
      alertPage:'和;'
    },
    模板:'<按钮NG点击=incrementPage()>增量网页< /按钮>,    链接:功能(范围,ELEM,ATTRS){
      scope.incrementPage =功能(){
          scope.page + = 1;
          scope.alertPage();
      }
    }
  }
})

HTML模板:

 <机身NG-应用='应用'NG控制器='myCtrl'>
    页面{{PAGE}}    <增量页=页面警报页='alertPage()'>< /增量>
  < /身体GT;


解决方案

为什么它不立即显示更新值的原因是因为只有2路绑定更新父(或指令的消费范围)范围的界值在消化周期。在NG-点击触发后消化周期发生的。因此 $ scope.page 在控制器尚未更新。你可以解决这个问题通过使用暂停将推迟采取行动,在消化周期结束时运行多种方式。您也可以通过设置其持有价值2路绑定属性的对象做到这一点。由于2路绑定属性和父范围共享相同的对象引用,你会立即看到变化。

方法1 - 使用超时:

  scope.incrementPage =功能(){
     scope.page + = 1;
     $超时(scope.alertPage)
  }

方法2 - 绑定的对象:

  //在你的控制器
 $ scope.page2 = {值:1};//在你的指令
scope.incrementPage =功能(){
     scope.page.value + = 1;
     scope.alertPage();
 }

Method3 - 通过使用函数值与参数绑定:

  //在你的控制器
$ scope.alertPage =功能(VAL){
  警报(VAL);
}

 <! - 在视图 - >
< D​​IV增量页=页警报页=alertPage(页)>< / DIV>

  //在该指令
scope.incrementPage =功能(){
     scope.page + = 1;
     scope.alertPage({页:scope.page});
 }

\r
\r

应用程序= angular.module('应用',[]);\r
\r
app.controller('myCtrl',函数($范围){\r
\r
  $ scope.page = 1;\r
  $ scope.page2 = {值:1};\r
  \r
  $ scope.alertPage =功能(){\r
    警报($ scope.page);\r
  }\r
  \r
  $ scope.alertPage2 =功能(){\r
    警报($ scope.page2.value);\r
  }\r
\r
})\r
\r
app.directive('增量',函数($超时){\r
  返回{\r
   \r
    范围: {\r
      页:'=',\r
      alertPage:'和;',\r
      第2页:=,\r
      alertPage2:'和;'\r
    },\r
    模板:'<按钮NG点击=incrementPage()>增量网页< /按钮>,\r
\r
    链接:功能(范围,ELEM,ATTRS){\r
      scope.incrementPage =功能(){\r
          scope.page + = 1;\r
          scope.page2.value + = 1;\r
          $超时(函数(){scope.alertPage()});\r
          scope.alertPage2();\r
      }\r
    }\r
  }\r
})

\r

&LT;脚本SRC =htt​​ps://ajax.googleapis.com/ajax /libs/angularjs/1.3.5/angular.min.js\"></script>\r
&LT; D​​IV NG-应用=应用程序NG控制器=myCtrl&GT;\r
  &LT; D​​IV增量页=页警报页=alertPage()第2页=第2页警报的第2页=alertPage2()&GT;&LT; / DIV&GT;\r
  &LT; / DIV&GT;

\r

\r
\r

In my directive, I have a controller variable, page which gets incremented when you press the button in the directive. However, the next line, scope.alertPage() which calls the controller function does not reflect this change. Notice, when you click the button page is still alerted as 1!

I know I can fix this by adding $scope.$apply in the controller but then I get the error that says a digest is already taking place.

Plunker: http://plnkr.co/edit/QSnBzM3gvJI9vnCkC19T?p=preview

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 template:

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

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

解决方案

The reason why it does not show the updated value immediately is because the 2 way binding updates the parent (or the consumer scope of the directive) scope's bound value only during the digest cycle. Digest cycle happens after the ng-click is triggered. And hence $scope.page in the controller is not yet updated. You can get around this in many ways by using a timeout which will defer the action to run at the end of the digest cycle. You could also do it by setting an object which holds the value as 2-way bound property. Since 2-way bound property and parent scope share the same object reference you will see the change immediately.

Method 1 - using a timeout:

  scope.incrementPage = function() {
     scope.page += 1;
     $timeout(scope.alertPage)
  }  

Method 2 - Bind an object:

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

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

Method3 - Pass the value using function binding with argument:

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

and

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

and

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

<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>

这篇关于改变指令的控制器范围的变量并没有反映在控制器的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆