繁体   English   中英

在 ngOnInit 中添加验证器时的 ExpressionChangedAfterItHasBeenCheckedError

[英]ExpressionChangedAfterItHasBeenCheckedError when add validator in 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);
    };
}

从控制台日志看来,验证器每次都返回相同的值。

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

我读了一个关于不在 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);
}

但随后错误更改为:

ERROR 错误:找不到名称为“网关”的控件


解决方案:

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

如果您查看 angular 的 github 问题页面,您可以找到与您遇到的同一问题相关的几张票(例如https://github.com/angular/angular/issues/15634 ,还有更多,我刚刚找到的这个作为示例)。 长话短说:angular 不喜欢某些(所有?)生命周期钩子中的视图更改。 在您的特定情况下究竟发生了什么变化:我假设这是 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.changeDetectorRef.detectChanges();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM