Angular 反应式表单验证:检查后表达式已更改

Angular Reactive Form Validation : Expression has changed after it was checked

我有一个带有自定义 FormControl 的响应式表单。第一次加载屏幕,虽然自定义控件是必填字段,但我的Form是有效的。

如果我触发任何更改,例如通过在我的表单中勾选一个复选框,那么该表单将被标记为无效,直到我向我的自定义控件填充一个值。

如果我重置了我的自定义控件的值,那么该表单将再次被标记为无效,并且从那时起它就会按预期工作。

所以只有当表单第一次加载到屏幕上时才会出现问题。

我注意到控制台中出现以下异常:

此错误是由我的自定义控件的验证器触发的,因为如果我对其进行注释,错误就会消失。

下面是我的自定义控件的代码。我做错了什么吗?

import { Component, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, FormControl, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
  selector: 'app-multiple-checkbox',
  templateUrl: './multiple-checkbox.component.html',
  styleUrls: ['./multiple-checkbox.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MultipleCheckboxComponent),
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => MultipleCheckboxComponent),
      multi: true
    }]
})
export class MultipleCheckboxComponent implements OnInit, ControlValueAccessor {

  value = [];
  disabled = false;

  @Input() public options: { key, value }[];

  onTouched: any;
  onChange: any;


  constructor() { }

  validate({ value }: FormControl) {
   
    const isNotValid = this.value.length === 0;
    return isNotValid && {
      invalid: true
    };
  }

  ngOnInit(): void { }

  evaluate(event, key): void {
    if (event.target.checked) {
      this.value.push(key);
    } else {
      this.value.splice(this.value.findIndex(i => key === i), 1);
    }

    this.onChange(this.value);
    this.onTouched();
  }

  isChecked(key): boolean {
    return this.value.findIndex(e => e === key) > -1;
  }

  writeValue(value: any): void {
    this.value = value;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }
  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }

}

[编辑] 添加自定义控件在其父窗体中添加到屏幕的方式:

<div [formGroup]="form">
 <div *ngIf="control.visible">

    <div [ngSwitch]="control.controlType">

        <div *ngSwitchCase="'checkbox'">
            <label [attr.for]="control.key">{{control.label}}</label>

            <input [formControlName]="control.key" [id]="control.key" type="checkbox"
                (change)="evaluate(control.key)">
        </div>

<!--  THIS IS MY CUSTOM CONTROL -->

        <app-multiple-checkbox *ngSwitchCase="'multipleCheckbox'" [formControlName]="control.key"
            [options]="control.options" (change)="evaluate(control.key)">
        </app-multiple-checkbox>
    </div>
</div>

[编辑]

在下面的评论之后,错误是由我表单中的这一行触发的:

<button type="submit" color="accent" (click)="save()" 
 [disabled]="catalogForm.invalid">Submit</button>

Expression has changed after it was checked

以上错误只出现在开发模式下。 在生产中不存在此错误。

在开发模式下消除这个错误

import ChangeDetectorRef from  @angular/core

constructor(private changeDecRef:ChangeDetectorRef) {}

然后

    if (event.target.checked) {
      this.value.push(key);
    } else {
      this.value.splice(this.value.findIndex(i => key === i), 1);
    }

    this.onChange(this.value);
    this.onTouched();

    /// ADD THIS FUNCTION ///
    this.changeDecRef.detectChanges();
  }```