2) 我一直试图找出 ngModelControllers 的存储位置,以便我可以查看调试器中的情况,但无法找到它们。使用 ngModel 指令时,我应该在作用域或父作用域中看到这些吗? (他们住在哪里?!?)
答案取决于您想从哪里访问控制器。
从元素外部用ng-model
它需要具有ng-model 属性的元素和父表单(或ngForm)的“名称”属性。因此,假设您有名称为myForm 的表单和名称为myInput 的属性ng-model 的元素,那么您可以从父作用域以myForm.myInput 访问ngModelController 的myFoo。例如,出于调试目的:
<p>myFoo: {{myForm.myInput.$modelValue}}<p>
<form name="myForm">
<div ng-controller="InnerController" name="myInput" ng-model="model.foo"></div>
</form>
可以在http://plnkr.co/edit/IVTtvIXlBWXGytOEHYbn?p=preview看到
从带有ng-model的元素内部
类似于answer from @pixelbits,由于控制器创建的顺序需要使用$evalAsync,但您也可以使用angular.element.controller函数来检索它:
app.controller('InnerController', function($scope, $element) {
$scope.$evalAsync(function() {
$scope.myModelController = $element.controller('ngModel');
});
});
用于,在控制器内部查看它,用于调试目的,如:
<div ng-controller="InnerController" ng-model="model.foo">
<p>myFoo: {{myModelController.$modelValue}}<p>
</div>
可以在http://plnkr.co/edit/C7ykMHmd8Be1N1Gl1Auc?p=preview 看到。
1) 有没有办法使用 ngModel 和普通控制器来获得上述效果?
在指令中添加ngModelController 后,您可以更改其值,就像使用自定义指令访问ngModelController 一样,使用$setViewValue 函数:
myModelController.$setViewValue('my-new-model-value');
您可以这样做,例如,响应触发ngChange 处理程序的用户操作。
app.controller('InnerController', function($scope, $element) {
$scope.$evalAsync(function() {
$scope.myModelController = $element.controller('ngModel');
});
$scope.$watch('myModelController.$modelValue', function(externalModel) {
$scope.localModel = externalModel;
});
$scope.changed = function() {
$scope.myModelController.$setViewValue($scope.localModel);
};
});
注意$modelValue 上的额外观察者以获取模型的初始值,以及对以后的任何更改做出反应。
它可以与以下模板一起使用:
{{model.foo}}
<div ng-controller="InnerController" ng-model="model.foo">
<p><input type="text" ng-model="localModel" ng-change="changed()"></p>
</div>
请注意,这使用ngChange 而不是localModel 上的观察者。这是故意的,以便仅在用户与元素交互时调用$setViewValue,而不是响应父范围对模型的更改。
这可以在http://plnkr.co/edit/uknixs6RhXtrqK4ZWLuC?p=preview看到
编辑:如果你想避免$evalAsync,你可以使用观察者来代替。
$scope.$watch(function() {
return $element.controller('ngModel');
}, function(ngModelController) {
$scope.myModelController = ngModelController;
});
如http://plnkr.co/edit/gJonpzLoVsgc8zB6tsZ1?p=preview所见
作为旁注,到目前为止,我似乎避免像这样嵌套普通控制器。我认为如果模板角色的某个部分是通过ngModel 控制变量,那么它是编写一个小指令的主要候选者,通常具有一个孤立的范围,以确保没有由于范围继承而产生的意外影响,它有一个清晰的 API,并使用require 访问ngModelController。是的,它可能不会被重用,但它确实有助于实现代码各部分之间的职责分离。