javascript 如何观看指令的指令 ng-model
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22819494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Watch Directive's Directive ng-model
提问by Neel
I have a directive that uses the parent scope in that view. This directive has a child directive that uses an isolated scope. I am trying to get the parent directive to watch any changes done to the ngModel of the child directive and update its own modal if changes were made. Here is a jsfiddle that probably explains better: http://jsfiddle.net/Alien_time/CnDKN/
我有一个在该视图中使用父作用域的指令。该指令有一个使用隔离作用域的子指令。我试图让父指令观察对子指令的 ngModel 所做的任何更改,并在进行更改时更新其自己的模式。这是一个 jsfiddle,可能解释得更好:http: //jsfiddle.net/Alien_time/CnDKN/
Here is the code:
这是代码:
<div ng-app="app">
<div ng-controller="MyController">
<form name="someForm">
<div this-directive ng-model="theModel"></div>
</form>
</div>
</div>
Javascript:
Javascript:
var app = angular.module('app', []);
app.controller('MyController', function() {
});
app.directive('thisDirective', function($compile, $timeout) {
return {
scope: false,
link: function(scope, element, attrs) {
var ngModel = attrs.ngModel;
var htmlText = '<input type="text" ng-model="'+ ngModel + '" />' +
'<div child-directive ng-model="'+ ngModel + '"></div>';
$compile(htmlText)(scope, function(_element, _scope) {
element.replaceWith(_element);
});
// Not sure how to watch changes in childDirective's ngModel ???????
}, // end link
} // end return
});
app.directive('childDirective', function($compile, $timeout) {
return {
scope: {
ngModel: '='
},
link: function(scope, element, attrs, ngModel) {
var htmlText = '<input type="text" ng-model="ngModel" />';
$compile(htmlText)(scope, function(_element, _scope) {
element.replaceWith(_element);
});
// Here the directive text field updates after some server side process
scope.ngModel = scope.dbInsertId;
scope.$watch('dbInsertId', function(newValue, oldValue) {
if (newValue)
console.log("I see a data change!"); // Delete this later
scope.ngModel = scope.imageId;
}, true);
},
} // end return
});
In the example, you can see that there is a text input inside a parent directive as well as its child directive. If you type inside each of them, the other model gets updated since they are binded by ngmodel
. However, the child directive's text input gets updated after a server connection. When that happens, the text input in the parent directive doesnt get updated. So I think I need to watch the ngModel inside the child directive for any changes. How can I do that? Does it make sense?
在示例中,您可以看到在父指令及其子指令中都有一个文本输入。如果您在每个模型中键入,则另一个模型会更新,因为它们由ngmodel
. 但是,子指令的文本输入在服务器连接后更新。发生这种情况时,父指令中的文本输入不会更新。所以我想我需要观察子指令中的 ngModel 是否有任何更改。我怎样才能做到这一点?是否有意义?
回答by JoseM
As @shaunhusain mentioned you have to use the ngModelController to interact with ngModel. On the ngModelController you can set up a watch on the $modelValue
and you can change the value in the model by calling $setViewValue
. Remeber that to use the ngModelController you need to add a require: "ngModel"
to your directive definition object.
正如@shaunhusain 提到的,您必须使用 ngModelController 与 ngModel 进行交互。在 ngModelController 上,您可以在 上设置监视,$modelValue
并且可以通过调用$setViewValue
. 请记住,要使用 ngModelController,您需要将 a 添加require: "ngModel"
到指令定义对象中。
When you get a value from outside of angular (like from your database) and you in turn want to use that value to change the model value, you need to wrap that code in a scope.$apply()
当您从 angular 外部(例如从您的数据库中)获得一个值并且您又想使用该值来更改模型值时,您需要将该代码包装在一个 scope.$apply()
app.directive('thisDirective', function($compile, $timeout, $log) {
return {
scope: false,
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
...
scope.$watch(
function(){
return ngModel.$modelValue;
}, function(newValue, oldValue){
$log.info('in *thisDirective* model value changed...', newValue, oldValue);
}, true);
}, // end link
} // end return
});
app.directive('childDirective', function($compile, $timeout, $log) {
return {
scope: {
ngModel: '='
},
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
...
scope.$watch(
function(){
return ngModel.$modelValue;
}, function(newValue, oldValue){
$log.info('in *childDirective* model value changed...', newValue, oldValue);
}, true);
// make believe change by server
setTimeout(function() {
scope.$apply(function() {
ngModel.$setViewValue('set from the server...');
};
},5000);
},
} // end return
});
relevant jsfiddle http://jsfiddle.net/CnDKN/2/
相关 jsfiddle http://jsfiddle.net/CnDKN/2/
BUTI don't think this is not really right usage of $setViewValue
. According to the docs, that is supposed to be used to update the value that is shown on the UI, not necessarily the model value.
但我认为这不是$setViewValue
. 根据文档,这应该用于更新 UI 上显示的值,不一定是模型值。
There is actually another way of making this work which I think is more straightforward and easier to use. Just use =attr
to set up bi-directional binding of the property you want to use in both thisDirective
and in childDirective
. And then you can just set up the the ng-model attribute setting in your directive and when you first use it you don't even need to know that it is using ng-model underneath.
实际上还有另一种方法可以使这项工作更加直接和易于使用。只需用于=attr
设置要在thisDirective
和 in 中使用的属性的双向绑定childDirective
。然后你可以在你的指令中设置 ng-model 属性设置,当你第一次使用它时,你甚至不需要知道它在下面使用 ng-model 。
Here is the code that shows you what I mean:
这是向您展示我的意思的代码:
app.directive('thisDirective', function($compile, $timeout, $log) {
return {
scope: {
thisval: '='
},
link: function(scope, element, attrs) {
var htmlText = '<input type="text" ng-model="thisval" />' +
'<div child-directive childval="thisval"></div>';
$compile(htmlText)(scope, function(_element, _scope) {
element.replaceWith(_element);
});
scope.$watch('thisval',function(newVal,oldVal){
$log.info('in *thisDirective* thisval changed...',
newVal, oldVal);
});
}, // end link
} // end return
});
app.directive('childDirective', function($compile, $timeout, $log) {
return {
scope: {
childval: '='
},
link: function(scope, element, attrs) {
var htmlText = '<input type="text" ng-model="childval" />';
$compile(htmlText)(scope, function(_element, _scope) {
element.replaceWith(_element);
});
scope.$watch('childval',function(newVal,oldVal){
$log.info('in *childDirective* childval changed...',
newVal, oldVal);
});
// make believe change that gets called outside of angular
setTimeout(function() {
// need to wrap the setting of values in the scope
// inside of an $apply so that a digest cycle will be
// started and have all of the watches on the value called
scope.$apply(function(){
scope.childval = "set outside of angular...";
});
},5000);
},
} // end return
});
Updated jsfiddle example: http://jsfiddle.net/CnDKN/3/
更新 jsfiddle 示例:http: //jsfiddle.net/CnDKN/3/