【问题标题】:FormBuilder Control causing "Expression has changed after it was checked" exceptionFormBuilder 控件导致“检查后表达式已更改”异常
【发布时间】:2016-05-03 08:52:16
【问题描述】:

我有一个通过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 相关。

Plunker of the issue | Plunker without modal

【问题讨论】:

标签: validation angular angular2-forms


【解决方案1】:

感谢qdoubleAngular Gitter 聊天中为我解决此问题。

这个问题似乎是由 Angular 解析页面的顺序引起的。通过从上到下,ngIf="!phone.valid"phone.valid 初始化之前被解析。这很容易通过在 if 语句中添加一个 catch 来确保它不是 null *ngIf="phone.valid === null ? false : !phone.valid"(或通过在输入之后移动标签)来解决。

【讨论】:

    【解决方案2】:

    这就是我遇到的问题。

    Angular 2 引入了一项功能来更好地处理更改检测。 Angular 2 放弃了摘要周期,转而采用单向流,这种流速度大约快 3-10 倍,并且可以更好地处理异步逻辑。

    @Component({
        ...
        changeDetection: ChangeDetectionStrategy.OnPush
    })...
    

    链接: 角度参考: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/

    【讨论】:

    【解决方案3】:

    使用 ngAfterContentChecked 修复了我这边的错误

    ngAfterContentChecked(): void {
        this.cd.detectChanges();
    }
    

    【讨论】:

    • 您也可以在异步更改代码的函数之后添加它 - 在我的情况下,它就在 this.control.setAsyncValidators(...) 之后。这迫使视图再次渲染,问题消失了。
    猜你喜欢
    • 2017-06-26
    • 2016-04-30
    • 2017-01-24
    • 1970-01-01
    • 2017-07-28
    • 2017-09-16
    • 1970-01-01
    • 2017-06-08
    • 2017-12-14
    相关资源
    最近更新 更多