Nee*_*eel 5 javascript angularjs angularjs-directive angularjs-scope angular-ngmodel
我有一个在该视图中使用父作用域的指令.该指令有一个使用隔离范围的子指令.我试图让父指令观察对子指令的ngModel所做的任何更改,并在更改时更新自己的模态.这是一个可能更好解释的jsfiddle:http://jsfiddle.net/Alien_time/CnDKN/
这是代码:
<div ng-app="app">
<div ng-controller="MyController">
<form name="someForm">
<div this-directive ng-model="theModel"></div>
</form>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
使用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
});
Run Code Online (Sandbox Code Playgroud)
在该示例中,您可以看到父指令内部有一个文本输入及其子指令.如果您在每个模型中键入内容,则另一个模型会更新,因为它们是绑定的ngmodel.但是,在服务器连接后,子指令的文本输入会更新.发生这种情况时,父指令中的文本输入不会更新.所以我想我需要在子指令中观察ngModel以进行任何更改.我怎样才能做到这一点?是否有意义?
Jos*_*seM 13
正如@shaunhusain所提到的,你必须使用ngModelController与ngModel进行交互.在ngModelController上,您可以设置监视$modelValue,您可以通过调用更改模型中的值$setViewValue.请记住,要使用ngModelController,您需要require: "ngModel"在指令定义对象中添加一个.
当你从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
});
Run Code Online (Sandbox Code Playgroud)
相关的jsfiddle http://jsfiddle.net/CnDKN/2/
但我不认为这不是正确的用法$setViewValue.根据文档,这应该用于更新UI上显示的值,而不一定是模型值.
实际上有另一种方法可以使这项工作更简单易用.只需用于=attr设置要在两者thisDirective中使用的属性的双向绑定childDirective.然后你可以在你的指令中设置ng-model属性设置,当你第一次使用它时,你甚至不需要知道它在下面使用ng-model.
这是代码,告诉你我的意思:
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
});
Run Code Online (Sandbox Code Playgroud)
更新了jsfiddle示例:http://jsfiddle.net/CnDKN/3/