Angular : 将查询参数绑定到 ExpressionChangedAfterItHasBeenCheckedError 中的表单字段结果
Angular : bind query parameter to form field results in ExpressionChangedAfterItHasBeenCheckedError
我创建了一个简单的指令,它从查询参数中获取输入并修补表单输入的值。该指令工作正常,但我收到此错误 ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'null'. Current value: 'testuser@test.be'
。
我在 SO / Google 上搜索了解决方案并尝试了一些,比如将我的指令的 ngOnInit 逻辑放在 ngAfterContentChecked 或 ngAfterContentInit 中,但错误仍然存在......
任何人都可以指出正确的方向来解决这个问题吗?
指令'bindQueryParamToInput'
import { Directive, Input } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[bindQueryParamToInput]'
})
export class BindQueryparamToInputDirective {
@Input('bindQueryParamToInput') paramKey: string;
constructor( private ngControl : NgControl) { }
ngOnInit() {
const queryParams = new URLSearchParams(location.search);
if (queryParams.has(this.paramKey)) {
this.ngControl.control.patchValue(queryParams.get(this.paramKey));
}
}
}
component.html 其中指令用于电子邮件字段
<div class="form-group" formGroupName="localAccountData">
<label>Emailadres</label>
<input formControlName="email"
type="text"
class="form-control"
placeholder="Email (login)"
bindQueryParamToInput="e">
</div>
component.ts 表单初始化的地方
@Component({
selector: 'gimmi-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
registrationForm: FormGroup;
constructor( ) { }
ngOnInit(): void {
this.registrationForm = new FormGroup ({
'personData': new FormGroup({
'firstName': new FormControl(null, Validators.required),
'lastName': new FormControl(null, Validators.required),
'birthday': new FormControl(null, Validators.required)
}),
'localAccountData': new FormGroup({
'email': new FormControl(null, [Validators.required, Validators.email]),
'password': new FormControl(null, [Validators.required])
})
});
}
}
编辑:接受的解决方案适用于上述情况。但是现在我把电子邮件字段放在一个单独的组件中(该指令现在在子组件中使用)现在 ExpressionChangedAfterItHasBeenCheckedError
又回来了... :-(
我已经尝试使用该解决方案并在子组件的 ngOnInit 中添加 this.ref.detectChanges()
,但是没有用...
我需要做些什么来解决子组件中的这个问题吗?
子组件电子邮件-input.ts
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'email-input',
templateUrl: './email-input.component.html',
styleUrls: ['./email-input.component.css']
})
export class EmailInputComponent implements OnInit {
@Input() parentFormGroup: FormGroup;
constructor() { }
ngOnInit(): void {
this.parentFormGroup.addControl( 'email', new FormControl(null, [Validators.required, Validators.email]));
}
}
subcomponent email-input.html(使用指令的地方)
div [formGroup]='parentFormGroup'>
<input formControlName="email"
type="text"
class="form-control"
placeholder="Email (login)"
bindQueryParamToInput="e">
</div>
在component.html中,我现在只使用<email-input></email-input>
组件。
另一个“标准”解决方案是命令更改检测。
constructor( private ngControl : NgControl, private ref: ChangeDetectorRef) { }
ngOnInit() {
const queryParams = new URLSearchParams(location.search);
if (queryParams.has(this.paramKey)) {
this.ngControl.control.patchValue(queryParams.get(this.paramKey));
this.ref.markForCheck();
// or, alternatively
this.ref.detectChanges();
}
}
我通过更改在更新表单控件值的行周围放置 setTimeout
解决了我在编辑中描述的问题。
setTimeout(() => {
this.ngControl.control.patchValue(queryParams.get(this.paramKey));
});
这可行,但感觉像是一种变通方法,而不是可靠的解决方案...
因此,非常感谢任何有助于获得更好解决方案的帮助
我创建了一个简单的指令,它从查询参数中获取输入并修补表单输入的值。该指令工作正常,但我收到此错误 ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'null'. Current value: 'testuser@test.be'
。
我在 SO / Google 上搜索了解决方案并尝试了一些,比如将我的指令的 ngOnInit 逻辑放在 ngAfterContentChecked 或 ngAfterContentInit 中,但错误仍然存在...... 任何人都可以指出正确的方向来解决这个问题吗?
指令'bindQueryParamToInput'
import { Directive, Input } from '@angular/core';
import { NgControl } from '@angular/forms';
@Directive({
selector: '[bindQueryParamToInput]'
})
export class BindQueryparamToInputDirective {
@Input('bindQueryParamToInput') paramKey: string;
constructor( private ngControl : NgControl) { }
ngOnInit() {
const queryParams = new URLSearchParams(location.search);
if (queryParams.has(this.paramKey)) {
this.ngControl.control.patchValue(queryParams.get(this.paramKey));
}
}
}
component.html 其中指令用于电子邮件字段
<div class="form-group" formGroupName="localAccountData">
<label>Emailadres</label>
<input formControlName="email"
type="text"
class="form-control"
placeholder="Email (login)"
bindQueryParamToInput="e">
</div>
component.ts 表单初始化的地方
@Component({
selector: 'gimmi-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
registrationForm: FormGroup;
constructor( ) { }
ngOnInit(): void {
this.registrationForm = new FormGroup ({
'personData': new FormGroup({
'firstName': new FormControl(null, Validators.required),
'lastName': new FormControl(null, Validators.required),
'birthday': new FormControl(null, Validators.required)
}),
'localAccountData': new FormGroup({
'email': new FormControl(null, [Validators.required, Validators.email]),
'password': new FormControl(null, [Validators.required])
})
});
}
}
编辑:接受的解决方案适用于上述情况。但是现在我把电子邮件字段放在一个单独的组件中(该指令现在在子组件中使用)现在 ExpressionChangedAfterItHasBeenCheckedError
又回来了... :-(
我已经尝试使用该解决方案并在子组件的 ngOnInit 中添加 this.ref.detectChanges()
,但是没有用...
我需要做些什么来解决子组件中的这个问题吗?
子组件电子邮件-input.ts
import { Component, Input, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'email-input',
templateUrl: './email-input.component.html',
styleUrls: ['./email-input.component.css']
})
export class EmailInputComponent implements OnInit {
@Input() parentFormGroup: FormGroup;
constructor() { }
ngOnInit(): void {
this.parentFormGroup.addControl( 'email', new FormControl(null, [Validators.required, Validators.email]));
}
}
subcomponent email-input.html(使用指令的地方)
div [formGroup]='parentFormGroup'>
<input formControlName="email"
type="text"
class="form-control"
placeholder="Email (login)"
bindQueryParamToInput="e">
</div>
在component.html中,我现在只使用<email-input></email-input>
组件。
另一个“标准”解决方案是命令更改检测。
constructor( private ngControl : NgControl, private ref: ChangeDetectorRef) { }
ngOnInit() {
const queryParams = new URLSearchParams(location.search);
if (queryParams.has(this.paramKey)) {
this.ngControl.control.patchValue(queryParams.get(this.paramKey));
this.ref.markForCheck();
// or, alternatively
this.ref.detectChanges();
}
}
我通过更改在更新表单控件值的行周围放置 setTimeout
解决了我在编辑中描述的问题。
setTimeout(() => {
this.ngControl.control.patchValue(queryParams.get(this.paramKey));
});
这可行,但感觉像是一种变通方法,而不是可靠的解决方案... 因此,非常感谢任何有助于获得更好解决方案的帮助