Pat*_*yer 7 angularjs angularjs-directive angularjs-scope
在我的应用程序中,我想保留对代码的某些部分使用普通控制器的选项 - 而不是为永远不会重复使用的一次性事物创建指令.
在这些情况下,我经常想要从控制器发布一些数据,以便在包含的部分中使用.现在,我知道我可以简单地绑定控制器范围内的项目,但是我想明确指定"模型"位置,以使代码更易于维护和更易于阅读.我想要使用的是ng-model,因为它将用于自定义指令,但只是在我的普通控制器旁边:
<div ng-controller="AppController" ng-model='fooModel'>
{{fooModel}}
</div>
Run Code Online (Sandbox Code Playgroud)
但是,我没有办法在不使用指令和'require'注入的情况下获得对生成的ngModelController的引用.
我知道我可以通过将$ attr注入到我的控制器中来轻松地创建自己的属性,并执行以下操作:
<div ng-controller="AppController" my-model='fooModel'>
{{fooModel}}
</div>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我只需手动获取或解析myModel值,并将我的模型粘贴到该名称下的$ scope中.但是在这种情况下感觉不对 - 我真的只需要一个控制器的"模型",并且我宁愿不必在ngModel存在时将这个样板添加到每个控制器.(这是事情的原则!)
我的问题是:
1)有没有办法使用ngModel和普通控制器来获得上述效果?
2)我一直在试图弄清楚ngModelControllers的存储位置,以便我可以查看调试器中的情况,但是无法找到它们.在使用ngModel指令时,我应该在范围或父范围内看到这些吗?(他们住在哪里?!?)
更新:如下面的答案所示,$ element.controller()可用于获取控制器.这工作(http://plnkr.co/edit/bZzdLpacmAyKy239tNAO?p=preview)然而,它有点不满意,因为它需要使用$ evalAsync.
2)我一直试图找出 ngModelController 的存储位置,以便我可以查看调试器中的情况,但一直无法找到它们。使用 ngModel 指令时,我应该在作用域还是父作用域中看到这些指令吗?(他们住在哪里?!?)
答案稍微取决于您想要从哪里访问控制器。
从元素外部ng-model
它需要具有该属性的元素ng-model和父表单(或ngForm)上都有“name”属性。假设您有带有 name 的表单myForm和带有ng-modelname 属性的元素myInput,那么您可以从父作用域 as访问ngModelControllerfor 。例如,出于调试目的:myFoomyForm.myInput
<p>myFoo: {{myForm.myInput.$modelValue}}<p>
<form name="myForm">
<div ng-controller="InnerController" name="myInput" ng-model="model.foo"></div>
</form>
Run Code Online (Sandbox Code Playgroud)
如http://plnkr.co/edit/IVTtvIXlBWXGytOEHYbn?p=preview所示
从元素内部ng-model
与@pixelbits 的答案类似,$evalAsync由于控制器创建的顺序,需要使用 using ,但您也可以使用 angular.element.controller 函数来检索它:
app.controller('InnerController', function($scope, $element) {
$scope.$evalAsync(function() {
$scope.myModelController = $element.controller('ngModel');
});
});
Run Code Online (Sandbox Code Playgroud)
在控制器内部用于查看它,以进行调试,如下所示:
<div ng-controller="InnerController" ng-model="model.foo">
<p>myFoo: {{myModelController.$modelValue}}<p>
</div>
Run Code Online (Sandbox Code Playgroud)
如http://plnkr.co/edit/C7ykMHmd8Be1N1Gl1Auc?p=preview所示。
1)是否有某种方法可以将 ngModel 与普通控制器一起使用来获得上述效果?
一旦您拥有ngModelController指令内部的内容,您就可以更改其值,就像使用自定义指令访问 一样ngModelController,使用以下$setViewValue函数:
myModelController.$setViewValue('my-new-model-value');
Run Code Online (Sandbox Code Playgroud)
例如,您可以执行此操作,以响应触发处理程序的用户操作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);
};
});
Run Code Online (Sandbox Code Playgroud)
请注意额外的观察者$modelValue以获取模型的初始值,并对任何后续更改做出反应。
它可以与如下模板一起使用:
{{model.foo}}
<div ng-controller="InnerController" ng-model="model.foo">
<p><input type="text" ng-model="localModel" ng-change="changed()"></p>
</div>
Run Code Online (Sandbox Code Playgroud)
请注意,这使用ngChange而不是 上的观察者localModel。这是故意的,因此$setViewValue仅在用户与元素交互时调用,而不是响应父范围对模型的更改。
这可以在http://plnkr.co/edit/uknixs6RhXtrqK4ZWLuC?p=preview看到
编辑:如果您想避免$evalAsync,您可以使用观察者。
$scope.$watch(function() {
return $element.controller('ngModel');
}, function(ngModelController) {
$scope.myModelController = ngModelController;
});
Run Code Online (Sandbox Code Playgroud)
如http://plnkr.co/edit/gJonpzLoVsgc8zB6tsZ1?p=preview所示
顺便说一句,到目前为止,我似乎已经避免了像这样嵌套普通控制器。我认为,如果模板的某个部分的作用是通过 控制变量ngModel,那么它是编写小指令的主要候选者,通常具有隔离的作用域,以确保不会因作用域继承而产生意外影响,并且具有明确的 API ,并用于require访问ngModelController. 是的,它可能不会被重用,但它确实有助于强制代码各部分之间的职责分离。
| 归档时间: |
|
| 查看次数: |
2097 次 |
| 最近记录: |