ExpressionChangedAfterItHasBeenCheckedError при добавлении валидатора в ngOnInit
Я пытаюсь добавить пользовательский валидатор к входу, но когда я это делаю, он вызывает ошибку ExpressionChangedAfterItHasBeenCheckedError, сообщающую, что что-то изменилось с ИСТИНЫ на ЛОЖЬ.
Я проследил проблему до строки ниже:
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, но это похоже на красную сельдь.
ОБНОВЛЕНИЕ: я попробовал:
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);
}
но тогда ошибка изменится на:
ОШИБКА Ошибка: не удается найти элемент управления с именем: "шлюз"
РЕШЕНИЕ:
Я проследил это до ошибки - используя реактивные формы + валидаторы + вкладки ngb. Добавление валидатора к элементу управления на вкладке вызывает ошибку. Единственное решение - перейти на шаблонные формы.
1 ответ
Если вы посмотрите на страницу Angular на github Issues, вы можете найти пару билетов, связанных с той же проблемой, что и у вас (например, https://github.com/angular/angular/issues/15634, есть и другие, этот я только что нашел в качестве примера). Короче говоря: angular не нравится изменение вида в некоторых (всех?) Хуках жизненного цикла. Что именно меняется в вашем конкретном случае: я предполагаю, что это состояние действительности formField (то есть внутренне в управляющем коде Angular, к которому у вас нет доступа), которое внутренне вызывает обнаружение изменений...
Если это возможно для вас, двигайтесь this.ipv4Fields.addControl()
для конструктора. Если это невозможно - см. Предложения в билетах GitHub (сделать detectChanges
, или же Promise
, или же setTimeout
, так далее.)...
ОБНОВИТЬ:
@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();
}
}