检查后表情发生了变化。以前的值:'ng-valid:true'。当前值:'ng-valid:false'

Liv*_*she 25 validation angular angular-reactive-forms angular6

我在父组件和子组件内的部分中有角反应形式。

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

我正在使用 setValidators 但出现错误

ParentFormComponent.html:3 ERROR 错误:ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改。以前的值:'ng-valid:true'。当前值:'ng-valid:false'。在 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 debugcore.NoChangesNode 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}

这是 ParentFormComponent.html:3 的行

 <form [formGroup]="parentForm" (ngSubmit)="submitForm()">
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

<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>
Run Code Online (Sandbox Code Playgroud)

并在 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);
 }
Run Code Online (Sandbox Code Playgroud)

小智 16

我遇到了同样的问题,我使用AfterViewCheckedand修复了它ChangeDetectorRef

import { AfterViewChecked, ChangeDetectorRef } from '@angular/core'

export class ClassName implements AfterViewChecked {
  constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}

  ngAfterViewChecked(): void {
    this.changeDetectorRef.detectChanges();
  }
}

Run Code Online (Sandbox Code Playgroud)

  • 即使这解决了问题,每次调用 `ngAfterViewChecked()` 生命周期钩子时调用 `detectChanges()` 也不是最佳选择。只需查看“ngAfterViewChecked()”被调用了多少次(使用“console.log”)。更好的解决方案是在需要时调用“detectChanges()”(对于主帖中的具体问题:在设置验证器之后)。 (15认同)
  • 有效,谢谢!如果能解释一下这个修复程序的作用就好了。每次 Angular 完成对组件及其子组件运行更改检测时,都会调用 *ngAfterVIewChecked*。很棒的介绍:https://indepth.dev/posts/1058/a-gentle-introduction-into-change-detection-in-angular (2认同)
  • 这是正确的解决方案 (2认同)
  • 正如@JoséAntonioPostigo上面提到的,`ngAfterViewChecked()`不是必需的。就我而言,在添加控件后立即单独调用“detectChanges()”效果很好。 (2认同)

moz*_*der 12

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

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

  • 根据您分享的 github 线程,这个“解决方案”实际上并不能解决错误,而只是隐藏它,并且可能会破坏很多东西。因此,在使用它之前,请确保 ChangeDetectionStrategy.OnPush 对您意味着什么 (2认同)

DIN*_*ari 7

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

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


Liv*_*she 3

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

<div *ngIf="db.checked" formGroupName="_monitorDB">
Run Code Online (Sandbox Code Playgroud)

<div [hidden]="!db.checked" formGroupName="_monitorDB">
Run Code Online (Sandbox Code Playgroud)