在ngOnInit中添加验证器时ExpressionChangedAfterItHasBeenCheckedError

时间:2017-09-07 16:30:50

标签: angular validation ngoninit

我正在尝试向输入添加自定义验证器,但是当我这样做时,它会触发ExpressionChangedAfterItHasBeenCheckedError错误,说明某些内容从TRUE更改为FALSE。

我将问题追溯到下面一行:

ngOnInit(): void {
    this.ipv4Fields.addControl('gateway', new FormControl('', [TabValidator.ipaddress()]));
}

如果我删除TabValidator.ipaddress(),则错误消失。同样,如果我的验证器强制返回'null',那么错误就会消失。我的验证器如下:

private static _ipaddress(address: string): any {
    console.log('checking ip address: '+address+' valid: '+ip.isV4Format(address)+' is null: '+(address === null ? 'yes' : 'no'));
    if (!ip.isV4Format(address)) { return { 'wrongFormat': true }; }
    console.log('returning null');
    return null;
}
public static ipaddress(): ValidatorFn {
    return (control: AbstractControl): { [key: string]: any } => {
        console.log('validator returning: '+TabValidator._ipaddress(control.value));
        return TabValidator._ipaddress(control.value);
    };
}

在控制台日志中,验证器每次都返回相同的值。

有人可以解释这里出了什么问题吗?我无法解释什么变量从'true'变为'false',因为上面的行中没有涉及布尔值。验证器如何在不出现在我的控制台日志中的情况下返回不同的值?

我读了一个关于不在ngOnInit中做事的SO问题,但这看起来像是一个红色的鲱鱼。

更新:我试过了:

ngOnInit(): void {
    Promise.resolve().then(() => {
    this.ipv4Fields.addControl('gateway', new FormControl('', [TabValidator.ipaddress()]));
    });
}

以及

ngOnInit(): void {
  setTimeout(() => this.ipv4Fields.addControl('gateway', new FormControl('', [TabValidator.ipaddress()])), 10);
}

但随后错误更改为:

  

错误错误:无法找到名称为“gateway”的控件

解决方案:

我追溯到一个错误 - 使用反应形式+验证器+ ngb标签。将验证器添加到选项卡上的控件会导致错误。唯一的解决方案是更改为模板表单。

1 个答案:

答案 0 :(得分:1)

如果你看一下angular的github问题页面,你可以找到与你遇到的同一问题相关的几张票(例如https://github.com/angular/angular/issues/15634,还有更多,我刚刚找到这个例子)。长话短说:角度不喜欢某些(所有?)生命周期钩子中的视图变化。你的具体情况究竟发生了什么变化:我认为这是formField的有效状态(即在Angular的控制代码内部,你无权访问),内部触发变更检测......

如果可以,请将this.ipv4Fields.addControl()移至构造函数。如果无法做到这一点 - 请参阅github门票中的建议(执行detectChangesPromisesetTimeout等)...

<强>更新

@Component(){}
export class MyComponent implements OnInit{

    @Input()
    ipv4Fields: FormGroup;

    //inject `ChangeDetecorRef`
    constructor(protected changeDetectorRef: ChangeDetectorRef){
    }

    ngOnInit(){
         this.ipv4Fields.addControl('gateway', new FormControl('', [TabValidator.ipaddress()]));
         this.chageDetectorRef.detectChanges();
    }
}