Angular 反应式表单验证:检查后表达式已更改
Angular Reactive Form Validation : Expression has changed after it was checked
我有一个带有自定义 FormControl
的响应式表单。第一次加载屏幕,虽然自定义控件是必填字段,但我的Form是有效的。
如果我触发任何更改,例如通过在我的表单中勾选一个复选框,那么该表单将被标记为无效,直到我向我的自定义控件填充一个值。
如果我重置了我的自定义控件的值,那么该表单将再次被标记为无效,并且从那时起它就会按预期工作。
所以只有当表单第一次加载到屏幕上时才会出现问题。
我注意到控制台中出现以下异常:
此错误是由我的自定义控件的验证器触发的,因为如果我对其进行注释,错误就会消失。
下面是我的自定义控件的代码。我做错了什么吗?
import { Component, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-multiple-checkbox',
templateUrl: './multiple-checkbox.component.html',
styleUrls: ['./multiple-checkbox.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MultipleCheckboxComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MultipleCheckboxComponent),
multi: true
}]
})
export class MultipleCheckboxComponent implements OnInit, ControlValueAccessor {
value = [];
disabled = false;
@Input() public options: { key, value }[];
onTouched: any;
onChange: any;
constructor() { }
validate({ value }: FormControl) {
const isNotValid = this.value.length === 0;
return isNotValid && {
invalid: true
};
}
ngOnInit(): void { }
evaluate(event, key): void {
if (event.target.checked) {
this.value.push(key);
} else {
this.value.splice(this.value.findIndex(i => key === i), 1);
}
this.onChange(this.value);
this.onTouched();
}
isChecked(key): boolean {
return this.value.findIndex(e => e === key) > -1;
}
writeValue(value: any): void {
this.value = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
[编辑]
添加自定义控件在其父窗体中添加到屏幕的方式:
<div [formGroup]="form">
<div *ngIf="control.visible">
<div [ngSwitch]="control.controlType">
<div *ngSwitchCase="'checkbox'">
<label [attr.for]="control.key">{{control.label}}</label>
<input [formControlName]="control.key" [id]="control.key" type="checkbox"
(change)="evaluate(control.key)">
</div>
<!-- THIS IS MY CUSTOM CONTROL -->
<app-multiple-checkbox *ngSwitchCase="'multipleCheckbox'" [formControlName]="control.key"
[options]="control.options" (change)="evaluate(control.key)">
</app-multiple-checkbox>
</div>
</div>
[编辑]
在下面的评论之后,错误是由我表单中的这一行触发的:
<button type="submit" color="accent" (click)="save()"
[disabled]="catalogForm.invalid">Submit</button>
Expression has changed after it was checked
以上错误只出现在开发模式下。
在生产中不存在此错误。
在开发模式下消除这个错误
import ChangeDetectorRef from @angular/core
constructor(private changeDecRef:ChangeDetectorRef) {}
然后
if (event.target.checked) {
this.value.push(key);
} else {
this.value.splice(this.value.findIndex(i => key === i), 1);
}
this.onChange(this.value);
this.onTouched();
/// ADD THIS FUNCTION ///
this.changeDecRef.detectChanges();
}```
我有一个带有自定义 FormControl
的响应式表单。第一次加载屏幕,虽然自定义控件是必填字段,但我的Form是有效的。
如果我触发任何更改,例如通过在我的表单中勾选一个复选框,那么该表单将被标记为无效,直到我向我的自定义控件填充一个值。
如果我重置了我的自定义控件的值,那么该表单将再次被标记为无效,并且从那时起它就会按预期工作。
所以只有当表单第一次加载到屏幕上时才会出现问题。
我注意到控制台中出现以下异常:
此错误是由我的自定义控件的验证器触发的,因为如果我对其进行注释,错误就会消失。
下面是我的自定义控件的代码。我做错了什么吗?
import { Component, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-multiple-checkbox',
templateUrl: './multiple-checkbox.component.html',
styleUrls: ['./multiple-checkbox.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MultipleCheckboxComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => MultipleCheckboxComponent),
multi: true
}]
})
export class MultipleCheckboxComponent implements OnInit, ControlValueAccessor {
value = [];
disabled = false;
@Input() public options: { key, value }[];
onTouched: any;
onChange: any;
constructor() { }
validate({ value }: FormControl) {
const isNotValid = this.value.length === 0;
return isNotValid && {
invalid: true
};
}
ngOnInit(): void { }
evaluate(event, key): void {
if (event.target.checked) {
this.value.push(key);
} else {
this.value.splice(this.value.findIndex(i => key === i), 1);
}
this.onChange(this.value);
this.onTouched();
}
isChecked(key): boolean {
return this.value.findIndex(e => e === key) > -1;
}
writeValue(value: any): void {
this.value = value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
}
[编辑] 添加自定义控件在其父窗体中添加到屏幕的方式:
<div [formGroup]="form">
<div *ngIf="control.visible">
<div [ngSwitch]="control.controlType">
<div *ngSwitchCase="'checkbox'">
<label [attr.for]="control.key">{{control.label}}</label>
<input [formControlName]="control.key" [id]="control.key" type="checkbox"
(change)="evaluate(control.key)">
</div>
<!-- THIS IS MY CUSTOM CONTROL -->
<app-multiple-checkbox *ngSwitchCase="'multipleCheckbox'" [formControlName]="control.key"
[options]="control.options" (change)="evaluate(control.key)">
</app-multiple-checkbox>
</div>
</div>
[编辑]
在下面的评论之后,错误是由我表单中的这一行触发的:
<button type="submit" color="accent" (click)="save()"
[disabled]="catalogForm.invalid">Submit</button>
Expression has changed after it was checked
以上错误只出现在开发模式下。 在生产中不存在此错误。
在开发模式下消除这个错误
import ChangeDetectorRef from @angular/core
constructor(private changeDecRef:ChangeDetectorRef) {}
然后
if (event.target.checked) {
this.value.push(key);
} else {
this.value.splice(this.value.findIndex(i => key === i), 1);
}
this.onChange(this.value);
this.onTouched();
/// ADD THIS FUNCTION ///
this.changeDecRef.detectChanges();
}```