Migré mi proyecto a angular 11 y noté que las validaciones globales que agregué hacen que FormBuilder.group obsoleto con el mensaje:
group is deprecated: This api is not typesafe and can result in issues with Closure Compiler renaming. Use the `FormBuilder#group` overload with `AbstractControlOptions` instead.así que esto está en desuso:
ingredientForm = this.fb.group({ ingredientType: ['', Validators.required], ingredientFlavor: [''], isMultiFlavor: [''], ingredientBrand: [''], ingredientName: [''], imageFile: [''] }, {validators: [ValidateThirdNumber.validate]}); y sin la opción de validators no lo es.
mi validador ValidateThirdNumber :
class ValidateThirdNumber { static validate(control: AbstractControl): void { if (control) { const isMultiFlavor = control.get('isMultiFlavor')?.value; const ingredientFlavor = control.get('ingredientFlavor')?.value; const ingredientBrand = control.get('ingredientBrand')?.value; const ingredientName = control.get('ingredientName')?.value; if (isMultiFlavor && ingredientFlavor.trim().length === 0) { control.get('ingredientFlavor')?.setErrors({required_if: true}); } else { control.get('ingredientFlavor')?.setErrors(null); } if (!ingredientFlavor && !ingredientBrand && !ingredientName) { control.get('ingredientName')?.setErrors({required_at_least: true}); control.get('ingredientFlavor')?.setErrors({required_at_least: true}); control.get('ingredientBrand')?.setErrors({required_at_least: true}); } else { control.get('ingredientName')?.setErrors(null); control.get('ingredientFlavor')?.setErrors(null); control.get('ingredientBrand')?.setErrors(null); } if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) { control.get('ingredientName')?.setErrors({not_the_same: true}); control.get('ingredientBrand')?.setErrors({not_the_same: true}); } } } }¿Cómo lo sobrecargo con AbstractControlOptions?
También recibo el mismo error, realizo los siguientes cambios.
asegúrese de que la firma de su función de validación coincida de esta manera. (Una función que recibe un control y devuelve sincrónicamente un mapa de errores de validación si está presente, de lo contrario es nulo).
y puede cambiar el código en el generador de formularios de esta manera.
y en el objeto formbuilder pase por encima del objeto formOptions como este
De la documentación vemos dos líneas diferentes con la función group()
group(controlsConfig: { [key: string]: any; }, options?: AbstractControlOptions): FormGroup
Y
group(controlsConfig: { [key: string]: any; }, options: { [key: string]: any; }): FormGroup
La segunda definición es lo que está en desuso.
¿La diferencia en estas líneas son las options?: AbstractControlOptions y options: { [key: string]: any; }
Para entender por qué angular arroja este error, ahora consideraremos AbstractControlOptions
interface AbstractControlOptions { validators?: ValidatorFn | ValidatorFn[] | null asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null updateOn?: 'change' | 'blur' | 'submit' } Continuamos desglosando el problema al notar que la diferencia entre esta estructura y su estructura es ValidatorFn[]
interface ValidatorFn { (control: AbstractControl): ValidationErrors | null } En general, el error se produce en su caso porque se espera que su función Validator tome un control y devuelva ValidationErrors | null En la línea validate(control: AbstractControl): void , su código en realidad devuelve void pero se espera que devuelva un ValidationError | null
De la descripción del problema, la solución es simplemente modificar el ValidatorFn
Asegúrese de que su ValidatorFn devuelva un ValidationError o, si no hay ningún error, devuelva un null de la definición de ValidationErrors
type ValidationErrors = { [key: string]: any; }; Deberá devolver un objeto de par de valores clave, por ejemplo {required_if: true}
Podemos cambiar su código agregando declaraciones de devolución como se esperaba
class ValidateThirdNumber { static validate(control: AbstractControl): ValidationErrors | null { if (control) { const isMultiFlavor = control.get('isMultiFlavor')?.value; const ingredientFlavor = control.get('ingredientFlavor')?.value; const ingredientBrand = control.get('ingredientBrand')?.value; const ingredientName = control.get('ingredientName')?.value; if (isMultiFlavor && ingredientFlavor.trim().length === 0) { control.get('ingredientFlavor')?.setErrors({required_if: true}); return ({required_if: true}); } else { control.get('ingredientFlavor')?.setErrors(null); } if (!ingredientFlavor && !ingredientBrand && !ingredientName) { control.get('ingredientName')?.setErrors({required_at_least: true}); control.get('ingredientFlavor')?.setErrors({required_at_least: true}); control.get('ingredientBrand')?.setErrors({required_at_least: true}); return ({required_at_least: true}); } else { control.get('ingredientName')?.setErrors(null); control.get('ingredientFlavor')?.setErrors(null); control.get('ingredientBrand')?.setErrors(null); } if (ingredientBrand && ingredientName && ingredientName === ingredientBrand) { control.get('ingredientName')?.setErrors({not_the_same: true}); control.get('ingredientBrand')?.setErrors({not_the_same: true}); return ({not_the_same: true}); } } return null; } }