Angular验证器先于@Input执行问题及解决方案咨询
解决Angular独立组件中@Input参数晚于表单验证器执行的问题
这个问题我之前也碰到过,核心原因是Angular组件的初始化顺序导致的——constructor会在@Input参数赋值前执行,所以你在constructor里初始化FormControl时,min和max还都是undefined。给你几个可行的解决方案,你可以根据自己的场景选择:
方案一:在ngOnInit中初始化FormControl
如果你的min和max参数在组件初始化后不会再变化,这个方案最简单。ngOnInit是Angular组件生命周期的钩子,会在@Input参数完成赋值后执行:
import { Component, Input, OnInit } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { CustomValidators } from './your-custom-validators-path'; export class InputComponent implements OnInit { @Input() min: number; @Input() max: number; formControl: FormControl; ngOnInit() { // 此时min和max已经拿到父组件传入的值了 this.formControl = new FormControl('', [ Validators.required, CustomValidators.minMax(this.min, this.max) ]); } }
方案二:用ngOnChanges动态更新验证器
如果min或max可能在组件生命周期中被父组件修改,那需要监听参数变化并更新验证器:
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { CustomValidators } from './your-custom-validators-path'; export class InputComponent implements OnInit, OnChanges { @Input() min: number; @Input() max: number; formControl: FormControl; ngOnInit() { this.initFormControl(); } ngOnChanges(changes: SimpleChanges) { // 当min或max发生变化(排除第一次初始化的变化)时,更新验证器 if ((changes.min && !changes.min.firstChange) || (changes.max && !changes.max.firstChange)) { this.updateValidators(); } } private initFormControl() { this.formControl = new FormControl('', [ Validators.required, CustomValidators.minMax(this.min, this.max) ]); } private updateValidators() { // 重新设置验证器 this.formControl.setValidators([ Validators.required, CustomValidators.minMax(this.min, this.max) ]); // 触发表单重新验证,emitEvent设为false避免不必要的valueChanges事件 this.formControl.updateValueAndValidity({ emitEvent: false }); } }
方案三:用@Input的setter监听参数变化
你也可以给min和max分别设置setter,每当参数更新时就同步更新验证器:
import { Component, Input, OnInit } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { CustomValidators } from './your-custom-validators-path'; export class InputComponent implements OnInit { private _min: number; private _max: number; formControl: FormControl; @Input() set min(value: number) { this._min = value; // 只有当FormControl已经初始化后才更新验证器 if (this.formControl) { this.updateValidators(); } } get min() { return this._min; } @Input() set max(value: number) { this._max = value; if (this.formControl) { this.updateValidators(); } } get max() { return this._max; } ngOnInit() { this.formControl = new FormControl('', [ Validators.required, CustomValidators.minMax(this._min, this._max) ]); } private updateValidators() { this.formControl.setValidators([ Validators.required, CustomValidators.minMax(this._min, this._max) ]); this.formControl.updateValueAndValidity({ emitEvent: false }); } }
注意事项
- 调用
updateValueAndValidity()时,添加{ emitEvent: false }可以避免触发valueChanges事件,防止不必要的组件更新,如果你需要触发事件可以去掉这个配置。 - 确保你的自定义验证器
CustomValidators.minMax能正确处理min和max的传入值,比如当参数未定义时可以做兼容处理(不过用上面的方案后,参数应该都能正确传入了)。
内容的提问来源于stack exchange,提问作者Amirhosein Al
相关产品推荐
相关产品推荐

