检查后,表达式已更改。以前的值:"ng-valid: true"。当前值:"ng-有效:假"



我在父组件中有角度反应形式,在子组件中有部分。

在子组件中,我有一个复选框,当它被选中时,会打开更多的字段,我希望它们都是必需的。

我正在使用setValidators,但我得到错误

ParentFormComponent.html:3错误错误:ExpressionChangedAfterIt HasBeenCheckedError:表达式已更改检查后。上一个值:"ng valid:true"。当前值:'ng-valid:false'。在viewDebugError(core.js:7601)at expressionChangedAfterIt HasBeenCheckedError(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 ERROR CONTEXT DebugContext_{view:Object,nodeIndex:2,nodeDef:Object,elDef:Object、elView:Object}

这是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);
}

我遇到了同样的问题,我使用AfterViewCheckedChangeDetectorRef:解决了它

import { AfterViewChecked, ChangeDetectorRef } from '@angular/core'
export class ClassName implements AfterViewChecked {
constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
ngAfterViewChecked(): void {
this.changeDetectorRef.detectChanges();
}
}

将父组件上的ChangeDetectionStrategy更改为:changeDetection: ChangeDetectionStrategy.OnPush。简单干净。

编辑这实际上不是一个解决方案,它只会隐藏错误。请查看评论中发布的github链接。

我面临着同样的问题,我知道这不是一种方法,但我找到的唯一解决方案是setTimeout

ngAfterViewInit(): void {
setTimeout(() => {
this.form.patchValue({
name: 'xyz',
email: 'abc@gmail.com',
phone: '0987654321'
})
}, );
}

我不知道这样做是否正确,但我通过更改解决了这个问题

<div *ngIf="db.checked" formGroupName="_monitorDB">

<div [hidden]="!db.checked" formGroupName="_monitorDB">

添加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
})

跟踪字段更改的位置并标记组件以进行更改检测。。。它可以是在一个函数中,也可以是像AfterViewChecked 这样的Angular生命周期挂钩之一

constructor(
private _cdr: ChangeDetectorRef
) {
}
// mark for check where change is happening
this._cdr.markForCheck();
this._cdr.detectChanges();

将变更检测更改为变更检测策略。OnPush也可以解决问题,但它可能会导致其他问题,您需要手动标记组件进行检查。

我倾向于从不使用setTimeout,因为我认为这是一种糟糕的做法,但我最近发现,在创建自定义组件和与DOM交互时,这有时是必要的。

然而,当我使用它时,它的延迟为0ms。只需在setTimeout中以无延迟包装操作就足以将操作移动到执行队列的末尾,这将解决Angular和DOM之间交互的许多问题。

TL,DR

setTimeout(() => actionThatCausesTheError(), 0);

试试这个:

ngOnInit():void
{
this._monitorDB.patchValue({
ServerName: 'ServerName',
DbName: 'DbName',
DB_tableName: 'DB_tableName',
DbPort: 'DbPort',
Query: 'Query',
Premissions:'Premissions'
});
}

最新更新