我在父组件中具有角电抗形式,在子组件中具有分段。
在子组件内部,我有一个复选框-选中该复选框时,会打开更多字段,我希望所有字段都必填。
我正在使用setValidators但出现错误
ParentFormComponent.html:3错误错误: ExpressionChangedAfterItHasBeenCheckedError:表达式已更改 经过检查后。先前的值:“ ng-valid:true”。当前值: 'ng-valid:false'。 在viewDebugError(core.js:7601) 在expressionChangedAfterItHasBeenCheckedError(core.js:7589) 在checkBindingNoChanges(core.js:7691) 在checkNoChangesNodeInline(core.js:10560) 在checkNoChangesNode(core.js:10541) 在debugCheckNoChangesNode(core.js:11144) 在debugCheckRenderNodeFn(core.js:11098) 在Object.eval [作为updateRenderer](ParentFormComponent.html:3) 在Object.debugUpdateRenderer [作为updateRenderer](core.js:11087) 在checkNoChangesView(core.js:10442)
ParentFormComponent.html:3错误上下文DebugContext_ {view:对象, nodeIndex:2,nodeDef:对象,elDef:对象,elView:对象}
这是ParentFormComponent.html:3的行
<form [formGroup]="parentForm" (ngSubmit)="submitForm()">
这是我的代码:
<label class="container">DB
<input #db type="checkbox" name="db" (change)="checkValue(db.name, db.checked)">
<span class="checkmark"></span>
</label>
<div *ngIf="db.checked" formGroupName="_monitorDB">
<mat-form-field>
<input matInput placeholder="Server name" formControlName="ServerName">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="DataBase name" formControlName="DbName">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="table name" formControlName="DB_tableName">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="port" formControlName="DbPort">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Query" formControlName="Query">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Permissions" formControlName="Premissions">
</mat-form-field>
</div>
并在ts文件中:
checkValue(name:string, event: any){
if (event == true){
this.test.push(name);
if (name =="db"){
this.childForm.get('_monitorDB').get('ServerName').setValidators([Validators.required]);
this.childForm.get('_monitorDB').get('DbName').setValidators([Validators.required]);
this.childForm.get('_monitorDB').get('DB_tableName').setValidators([Validators.required]);
this.childForm.get('_monitorDB').get('DbPort').setValidators([Validators.required]);
this.childForm.get('_monitorDB').get('Query').setValidators([Validators.required]);
this.childForm.get('_monitorDB').get('Premissions').setValidators([Validators.required]);
}
}
else{
const index: number = this.test.indexOf(name);
if (index !== -1) {
this.test.splice(index, 1);
if (name =="db"){
this.childForm.get('_monitorDB').get('ServerName').clearValidators();
this.childForm.get('_monitorDB').get('ServerName').updateValueAndValidity();
this.childForm.get('_monitorDB').get('DbName').clearValidators();
this.childForm.get('_monitorDB').get('DbName').updateValueAndValidity();
this.childForm.get('_monitorDB').get('DB_tableName').clearValidators();
this.childForm.get('_monitorDB').get('DB_tableName').updateValueAndValidity();
this.childForm.get('_monitorDB').get('DbPort').clearValidators();
this.childForm.get('_monitorDB').get('DbPort').updateValueAndValidity();
this.childForm.get('_monitorDB').get('Query').clearValidators();
this.childForm.get('_monitorDB').get('Query').updateValueAndValidity();
this.childForm.get('_monitorDB').get('Premissions').clearValidators();
this.childForm.get('_monitorDB').get('Premissions').updateValueAndValidity();
}
}
}
this.checkboxArr.emit(this.test);
}
答案 0 :(得分:7)
将父组件上的ChangeDetectionStrategy更改为:changeDetection: ChangeDetectionStrategy.OnPush
。简单干净。
答案 1 :(得分:2)
我遇到了相同的问题,并使用AfterViewChecked
和ChangeDetectorRef
进行了修复:
import { AfterViewChecked, ChangeDetectorRef } from '@angular/core'
export class ClassName implements AfterViewChecked {
constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
ngAfterViewChecked(): void {
this.changeDetectorRef.detectChanges();
}
}
答案 2 :(得分:1)
我面临着同样的问题,我知道这不是一种方法,但是我发现的唯一解决方案是setTimeout
ngAfterViewInit(): void {
setTimeout(() => {
this.form.patchValue({
name: 'xyz',
email: 'abc@gmail.com',
phone: '0987654321'
})
}, );
}
答案 3 :(得分:0)
我不知道这是否是正确的事情,但我通过更改来解决:
<div *ngIf="db.checked" formGroupName="_monitorDB">
到
<div [hidden]="!db.checked" formGroupName="_monitorDB">
答案 4 :(得分:0)
尝试这个:
ngOnInit():void
{
this._monitorDB.patchValue({
ServerName: 'ServerName',
DbName: 'DbName',
DB_tableName: 'DB_tableName',
DbPort: 'DbPort',
Query: 'Query',
Premissions:'Premissions'
});
}
答案 5 :(得分:0)
添加changeDetection: ChangeDetectionStrategy.OnPush
应该可以解决问题
@Component({
selector: 'app-test-center-location-step3',
templateUrl: './test-center-location-step3.component.html',
styleUrls: ['./test-center-location-step3.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
答案 6 :(得分:0)
跟踪字段更改的位置并标记组件以进行 changeDetection...它可以在一个函数或一个 Angular 生命周期钩子中,例如 AfterViewChecked
constructor(
private _cdr: ChangeDetectorRef
) {
}
// mark for check where change is happening
this._cdr.markForCheck();
this._cdr.detectChanges();
将changeDetection改为ChangeDetectionStrategy.OnPush也能解决问题,但可能会引起其他问题,需要手动标记组件进行检查。
答案 7 :(得分:0)
我倾向于从不使用 setTimeout
,因为我认为这是一种不好的做法,但我最近发现,在创建自定义组件并与 DOM 交互时,这有时是必要的。
但是,当我使用它时,延迟了 0ms
。只需将动作包装在setTimeout
中且无延迟就足以将动作移到执行队列的末尾,这将解决 Angular 和 DOM 之间交互的许多问题。
setTimeout(() => actionThatCausesTheError(), 0);