我们有以下情况:
有一个容器可以有 x 个输入元素 (x>= 0)每个输入元素使用正常的 ng 绑定
在容器中有一个函数,可以为每个包含的ngModelController添加一个$parsers和$validators。
代码如下:
<form-element>
<fs-input-a ng-required="true" ng-model="model.streetname" name="streetname"></fs-input-a>
<fs-input-b ng-required="true" ng-maxlength="5" ng-pattern="/d$/" ng-model="model.streetnr" name="streetnr"></fs-input-b>
</form-element>
在 "form-element" 指令的链接方法中,我们调用如下名称: var controls = element[0].querySelectorAll('[ng-model]'), i, ngModel;
// Get all ngModel controllers
if (controls.length) {
for (i = 0; i < controls.length; i++) {
ngModel = angular.element(controls[i]).controller('ngModel');
ngModel.$parsers.push(function(value) {
...
}.bind(ngModel));
ngModel.$validators.removeHidden = function() {
// on validation remove the hideError flag
this.$hideError = undefined;
return true;
}.bind(ngModel);
}
}
这在AngularJS 1.4.x下工作正常
在 AngularJS 1.5.x 中,只有当输入指令中的模板通过模板直接定义时,它才有效:"..."如果我们使用 templateUrl:"..."我们现在面临的问题是ngModel将是未定义的。在控件[i]中,我得到了正确的元素,并且有一个ng-model属性,但似乎AngularJS 1.5尚未编译该元素。
有没有更好的方法来操作子元素的 ngModels?
编译是懒惰的,所以没有办法像你目前那样可靠地做到这一点,父指令无法知道它的子指令已经编译并准备就绪。 $onInit
是在解析父/同级控制器时调用的,并且从 Angular 1.5.3 文档中$postLink
编译指令时调用的最后一个生命周期方法(很可能?):
$postLink() - 在此控制器的元素及其子元素已链接后调用。与 post-link 函数类似,此钩子可用于设置 DOM 事件处理程序并执行直接的 DOM 操作。请注意,包含
templateUrl
指令的子元素将不会编译和链接,因为它们正在等待其模板异步加载,并且它们自己的编译和链接已挂起,直到发生这种情况。
这似乎表明无论如何都不应该尝试通过 DOM 访问子控制器。
是否有任何特殊原因需要同时遍历所有控制器?如果您只是对所有控制器执行相同的初始化,那么另一种方法是将容器作为所需的控制器添加到子组件中并在那里进行,例如在子组件中:
require: {
...
parent: '^parentComponent'
},
controller: function() {
this.$onInit = () => this.parent.initialiseNgModel(...);
}
或者,如果无法修改子项,请使用 ng-init 或属性指令(或只是为了保持代码独立)。
如果绝对有必要,父控制器必须一次执行所有这些操作。然后,一个不太好的解决方案是为子组件添加一种方法,以指示它们已编译,父组件计算有多少个组件,并等待所有组件完成,然后再继续使用代码。