导致 "Expression has changed after it was checked" 异常的 FormBuilder 控件
FormBuilder Control causing "Expression has changed after it was checked" exception
我有一个通过 DynamicComponentLoader::loadIntoLocation
以编程方式实例化的表单。表单代码如下:
constructor (
private _builder: FormBuilder
) {
this.editForm = _builder.group({
name: ['', Validators.required],
email: ['', Validators.compose([Validators.required, Helpers.emailValidator])],
phone: [''],
phoneAlt: [''],
location: [''],
dob: [''],
bio: [''],
});
}
您会注意到某些表单没有验证器(据我所知,这与使用 Validators.nullValidator
相同,我已经对两者进行了测试)。
在我的模板中,我有以下代码(针对每个控件):
<label for="phone">Contact Number <span *ngIf="!phone.valid">- {{e(phone)}}</span></label>
<input type="text" name="phone" id="phone" ngControl="phone" #phone="ngForm">
第一个没有验证器的控件在遇到模板的 !phone.valid
部分时抛出以下异常两次:
EXCEPTION: Expression '!phone.valid in e@15:43' has changed after it was checked. Previous value: 'true'. Current value: 'false' in [!phone.valid in e@15:43]
在初始创建后,我在任何时候都不会触摸控件或 this.editForm
,因此,就我的代码而言,应该没有任何改变。
我知道我可以通过调用 enableProdMode()
来抑制错误,但我宁愿解决问题也不愿隐藏它。
编辑(2 月 8 日): 从那以后我尝试将模式的内容移动到单独的页面,但错误仍然存在。这表明问题与我创建和加载模式的方式无关,而是与 ControlGroup 或 FormBuilder 相关。
感谢 qdouble for solving this for me on the Angular Gitter 聊天。
问题似乎是由 angular 解析页面的顺序引起的。从上到下,ngIf="!phone.valid"
在 phone.valid
初始化之前被解析。通过在 if 语句中添加一个 catch 以确保它不为空 *ngIf="phone.valid === null ? false : !phone.valid"
(或通过在输入后移动标签),可以轻松解决此问题。
这是我 运行 遇到的问题。
Angular 2 引入了一项功能以更好地处理变更检测。 Angular 2 放弃摘要周期以支持 one-way 流程,这大约快 3-10 倍并且可以更好地处理异步逻辑。
@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush
})...
链接:
Angular参考:https://angular.io/docs/ts/latest/api/core/index/ChangeDetectionStrategy-enum.html
了解变化检测:https://auth0.com/blog/understanding-angular-2-change-detection/
Angular 2 变化检测的工作原理:http://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
使用 ngAfterContentChecked 修复了我这边的错误
ngAfterContentChecked(): void {
this.cd.detectChanges();
}
我有一个通过 DynamicComponentLoader::loadIntoLocation
以编程方式实例化的表单。表单代码如下:
constructor (
private _builder: FormBuilder
) {
this.editForm = _builder.group({
name: ['', Validators.required],
email: ['', Validators.compose([Validators.required, Helpers.emailValidator])],
phone: [''],
phoneAlt: [''],
location: [''],
dob: [''],
bio: [''],
});
}
您会注意到某些表单没有验证器(据我所知,这与使用 Validators.nullValidator
相同,我已经对两者进行了测试)。
在我的模板中,我有以下代码(针对每个控件):
<label for="phone">Contact Number <span *ngIf="!phone.valid">- {{e(phone)}}</span></label>
<input type="text" name="phone" id="phone" ngControl="phone" #phone="ngForm">
第一个没有验证器的控件在遇到模板的 !phone.valid
部分时抛出以下异常两次:
EXCEPTION: Expression '!phone.valid in e@15:43' has changed after it was checked. Previous value: 'true'. Current value: 'false' in [!phone.valid in e@15:43]
在初始创建后,我在任何时候都不会触摸控件或 this.editForm
,因此,就我的代码而言,应该没有任何改变。
我知道我可以通过调用 enableProdMode()
来抑制错误,但我宁愿解决问题也不愿隐藏它。
编辑(2 月 8 日): 从那以后我尝试将模式的内容移动到单独的页面,但错误仍然存在。这表明问题与我创建和加载模式的方式无关,而是与 ControlGroup 或 FormBuilder 相关。
感谢 qdouble for solving this for me on the Angular Gitter 聊天。
问题似乎是由 angular 解析页面的顺序引起的。从上到下,ngIf="!phone.valid"
在 phone.valid
初始化之前被解析。通过在 if 语句中添加一个 catch 以确保它不为空 *ngIf="phone.valid === null ? false : !phone.valid"
(或通过在输入后移动标签),可以轻松解决此问题。
这是我 运行 遇到的问题。
Angular 2 引入了一项功能以更好地处理变更检测。 Angular 2 放弃摘要周期以支持 one-way 流程,这大约快 3-10 倍并且可以更好地处理异步逻辑。
@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush
})...
链接: Angular参考:https://angular.io/docs/ts/latest/api/core/index/ChangeDetectionStrategy-enum.html
了解变化检测:https://auth0.com/blog/understanding-angular-2-change-detection/
Angular 2 变化检测的工作原理:http://blog.angular-university.io/how-does-angular-2-change-detection-really-work/
使用 ngAfterContentChecked 修复了我这边的错误
ngAfterContentChecked(): void {
this.cd.detectChanges();
}