ada*_*eck 5 javascript angular2-forms angular2-template angular
我创建了一个包含表单的自定义组件<address></address>。我有一个父组件,其中包含以下数组:
@ViewChildren(AddressComponent) addressComponents: QueryList<AddressComponent>;
Run Code Online (Sandbox Code Playgroud)
因此,父级可以包含这些元素的集合,并且用户可以根据他们将输入的地址数量添加和删除它们。
家长还有一个按钮,可以在用户输入所有所需的地址后继续。但是,该<address>组件必须正确填写<address>,因此我在该组件上有一个公共 getter :
get valid(): boolen {
return this._form.valid;
}
Run Code Online (Sandbox Code Playgroud)
回到父级上的按钮。<address>如果任何组件无效,则需要禁用它。所以我写了以下内容:
get allValid() {
return this.addressComponents && this.addressComponents.toArray().every(component => component.valid);
}
Run Code Online (Sandbox Code Playgroud)
在父模板中:
<button [disabled]="!allValid" (click)="nextPage()">Proceed</button>
Run Code Online (Sandbox Code Playgroud)
但 Angular 不喜欢这样,因为addressComponents直到生命周期事件才在父级中定义ngAfterViewInit。由于它立即运行,ngOnViewInit()我得到了导致错误的表达式检查的两个不同值。(至少我认为是这样)。
如何在模板中使用依赖于 的属性ngAfterViewInit?或者告诉我的父母其所有孩子都是有效的最好方法是什么?
错误消息:
检查后表情发生了变化。以前的值:“假”。当前值:“真”
更新:
所以我console.log编辑了 的返回值allValid并第一次注意到它是undefined。这是预料之中的,this.addressComponents直到。这是下一个日志,这令人惊讶,因为我的页面上还没有任何组件。我正在父组件中使用模拟数据(尽管全部有效)来创建组件。我确实了解到(在空数组上返回 true)。所以对 的第三次调用正在返回。我再次感到有点惊讶,因为我的所有数据都是有效的。在第四条日志中,它返回了,这正是我所期望的。所以我假设返回的最终值是 Angular 不喜欢的。undefinedngAfterInittrue<address>ngOnInit[].every...console.logfalsetrue
无论如何,我能够解决这个问题。我不知道我是否真的在解决问题或只是抑制错误。我不喜欢这个解决方案,所以我将保持这个问题的开放,以获得更好的解决方案。
get allValid() {
return this.addressComponents && this.addressComponents.length > 0 && this.addressComponents().toArray().every(component => component.valid);
}
Run Code Online (Sandbox Code Playgroud)
所以我认为正在发生的事情:
第一波变更检测会让您的函数返回 false,然后您的父组件在视图实例化后找到此信息(然后返回 true)。在“dev”模式下,Angular 运行更改检测两次,以确保更改检测后不会发生更改(当然,因为更改检测应该检测所有更改!)
根据这里找到的答案:
Angular2 - 表达式在检查后已更改 - 通过调整大小事件绑定到 div 宽度
使用 AfterViewInit 可能会导致这些问题,因为它可能会在更改检测完成后运行。
将您的分配包含在超时中可以解决此问题,因为它会在设置值之前等待一个时间点。
ngAfterViewInit(){
setTimeout(_ => this.allValid = this.addressComponents && this.addressComponents.toArray().every(component => component.valid));
}
Run Code Online (Sandbox Code Playgroud)
由于这些原因,我不会在这样的模板变量上使用 getter,因为视图初始化可能会在更改检测完成后更改值。