I have angular reactive form in parent component and sections inside childrens component.
Inside the child component I have a checkbox - when its checked - more fields open and I want them all to be required.
I am using setValidators but I'm getting error
ParentFormComponent.html:3 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ng-valid: true'. Current value: 'ng-valid: false'. at viewDebugError (core.js:7601) at expressionChangedAfterItHasBeenCheckedError (core.js:7589) at checkBindingNoChanges (core.js:7691) at checkNoChangesNodeInline (core.js:10560) at checkNoChangesNode (core.js:10541) at debugCheckNoChangesNode (core.js:11144) at debugCheckRenderNodeFn (core.js:11098) at Object.eval [as updateRenderer] (ParentFormComponent.html:3) at Object.debugUpdateRenderer [as updateRenderer] (core.js:11087) at checkNoChangesView (core.js:10442)
ParentFormComponent.html:3 ERROR CONTEXT DebugContext_ {view: Object, nodeIndex: 2, nodeDef: Object, elDef: Object, elView: Object}
this is the line of ParentFormComponent.html:3
<form [formGroup]="parentForm" (ngSubmit)="submitForm()">
Here is my code:
<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>
and in the ts file:
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); }
Navigate up the call stack until you find a template expression where the value displayed in the error has changed. Ensure that there are no changes to the bindings in the template after change detection is run. This often means refactoring to use the correct component lifecycle hook for your use case.
I faced the same issue and I fixed it by using AfterViewChecked
and ChangeDetectorRef
:
import { AfterViewChecked, ChangeDetectorRef } from '@angular/core' export class ClassName implements AfterViewChecked { constructor(private readonly changeDetectorRef: ChangeDetectorRef) {} ngAfterViewChecked(): void { this.changeDetectorRef.detectChanges(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With