hte*_*lez 51 angularjs angularjs-directive angularjs-ng-change
我有一个模板的指令
<div>
<div ng-repeat="item in items" ng-click="updateModel(item)">
<div>
Run Code Online (Sandbox Code Playgroud)
我的指令被声明为:
return {
templateUrl: '...',
restrict: 'E',
require: '^ngModel',
scope: {
items: '=',
ngModel: '=',
ngChange: '&'
},
link: function postLink(scope, element, attrs)
{
scope.updateModel = function(item)
{
scope.ngModel = item;
scope.ngChange();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望ng-change在单击某个项目时调用,foo并且已经更改了值.
也就是说,如果我的指令实现为:
<my-directive items=items ng-model="foo" ng-change="bar(foo)"></my-directive>
Run Code Online (Sandbox Code Playgroud)
我希望在更新bar值时调用foo.
使用上面给出的代码,ngChange成功调用,但使用旧值foo而不是新更新值调用它.
解决该问题的一种方法是调用ngChange内部超时以在将来的某个时刻执行它,此时值foo已经更改.但是这个解决方案让我可以放松地控制事情的执行顺序,我认为应该有一个更优雅的解决方案.
我也可以foo在父作用域中使用一个观察者,但是这个解决方案并没有真正给出一个ngChange方法,我被告知观察者是伟大的记忆消费者.
有没有办法在ngChange没有超时或观察者的情况下同步执行?
Sam*_*nen 58
如果你需要ngModel,你可以叫$setViewValue上ngModelController,它隐评估ng-change.链接函数的第四个参数应该是ngModelCtrl.以下代码将为ng-change您的指令工作.
link : function(scope, element, attrs, ngModelCtrl){
scope.updateModel = function(item) {
ngModelCtrl.$setViewValue(item);
}
}
Run Code Online (Sandbox Code Playgroud)
为了使您的解决方案有效,请从myDirective的隔离范围中删除ngChange和ngModel.
这是一个插件:http://plnkr.co/edit/UefUzOo88MwOMkpgeX07?p = preview
小智 14
TL;博士
根据我的经验,您只需要从ngModelCtrl继承.的ng-change表达式将当您使用的方法进行自动评估ngModelCtrl.$setViewValue
angular.module("myApp").directive("myDirective", function(){
return {
require:"^ngModel", // this is important,
scope:{
... // put the variables you need here but DO NOT have a variable named ngModel or ngChange
},
link: function(scope, elt, attrs, ctrl){ // ctrl here is the ngModelCtrl
scope.setValue = function(value){
ctrl.$setViewValue(value); // this line will automatically eval your ng-change
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
更确切地说
ng-change在ngModelCtrl.$commitViewValue() IF期间评估ngModel的对象引用已更改.如果您不使用trigger参数或未准备任何ngModelOptions$commitViewValue(),$setViewValue(value, trigger)则会自动调用该方法.
我指定如果更改的引用ng-chage将自动触发.当你是a 或a时,你不必担心它.如果你是一个对象而你只是改变了它的一些属性,那么就不会进行评估.$viewValuengModelstringintngModel$setViewValuengChange
如果我们从帖子的开头拿到代码示例
scope.setValue = function(value){
ctrl.$setViewValue(value); // this line will automatically evalyour ng-change
};
scope.updateValue = function(prop1Value){
var vv = ctrl.$viewValue;
vv.prop1 = prop1Value;
ctrl.$setViewValue(vv); // this line won't eval the ng-change expression
};
Run Code Online (Sandbox Code Playgroud)
经过一些研究,似乎最好的方法是使用$timeout(callback, 0).
它$digest在执行回调后立即自动启动一个循环.
所以,在我的情况下,解决方案是使用
$timeout(scope.ngChange, 0);
Run Code Online (Sandbox Code Playgroud)
这样,回调的签名无关紧要,它将按照您在父作用域中定义的那样执行.
以下是有这些变化的傻瓜: http ://plnkr.co/edit/9MGptJpSQslk8g8tD2bZ?p = preview
| 归档时间: |
|
| 查看次数: |
56190 次 |
| 最近记录: |