检查后表达式已更改。先前的值:“ ng-valid:true”。当前值:“ ng-valid:false”

时间:2018-12-23 05:18:36

标签: angular validation angular6 angular-reactive-forms

我在父组件中具有角电抗形式,在子组件中具有分段。

在子组件内部,我有一个复选框-选中该复选框时,会打开更多字段,我希望所有字段都必填。

我正在使用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);
 }

8 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:2)

我遇到了相同的问题,并使用AfterViewCheckedChangeDetectorRef进行了修复:

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 之间交互的许多问题。

TL,DR

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