0

我们有以下场景:

有一个容器可以有 x 个输入元素 (x >= 0) 每个输入元素都使用普通的 ng-binds

在容器中有一个函数可以为每个包含的 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 中,它只有在输入指令中的模板直接通过 template: '...' 定义时才有效。如果我们使用 templateUrl: '...' 我们现在会遇到 ngModel 未定义的问题。在 controls[i] 中,我得到了正确的元素,并且有一个 ng-model 属性,但 AngularJS 1.5 似乎还没有编译该元素。

有没有更好的方法来操作子元素的 ngModels?

4

1 回答 1

0

编译是懒惰的,所以没有办法像你目前得到的那样可靠地做到这一点,父指令无法知道它的子指令是否已编译并准备好。$onInit在解析父/兄弟控制器时调用,并且从Angular 1.5.3 docs开始,$postLink这(很可能?)是编译指令时调用的最后一个生命周期方法:

$postLink() - 在这个控制器的元素和它的子元素被链接之后调用。与 post-link 函数类似,此钩子可用于设置 DOM 事件处理程序并进行直接 DOM 操作。请注意,包含templateUrl指令的子元素将不会被编译和链接,因为它们正在等待其模板异步加载,并且它们自己的编译和链接已暂停,直到发生这种情况。

这似乎是说无论如何您都不应该尝试通过 DOM 访问子控制器。

是否有任何特殊原因需要同时遍历所有控制器?如果您只是对所有控制器进行相同的初始化,那么另一种方法是将容器作为必需的控制器添加到子组件中并在那里执行,例如在子组件中:

require: {
  ...
  parent: '^parentComponent'
},
controller: function() {
  this.$onInit = () => this.parent.initialiseNgModel(...);
}

或者,如果无法修改子项(或仅将代码分开),请使用 ng-init 或属性指令。

如果父控制器必须一次完成所有这些是绝对必要的。然后一个不太好的解决方案是为子组件添加一种方式来表示它们已经编译,并且父组件会计算有多少,并等待所有组件都完成,然后再继续执行您的代码。

于 2016-04-08T17:51:27.703 回答