Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FormBuilder group is deprecated

I migrated my project to angular 11 and I noticed that the global validations that I added make FormBuilder.group deprecated with the message:

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. 

so this is deprecated:

  ingredientForm = this.fb.group({     ingredientType: ['', Validators.required],     ingredientFlavor: [''],     isMultiFlavor: [''],     ingredientBrand: [''],     ingredientName: [''],     imageFile: ['']   }, {validators: [ValidateThirdNumber.validate]}); 

and without the validators option it's not.

my ValidateThirdNumber validator:

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});       }     }   } } 

how do I overload it with AbstractControlOptions ?

like image 963
ufk Avatar asked Dec 05 '20 08:12

ufk


2 Answers

Problem description

From the documentation we see two different lines with the group() function

group(controlsConfig: { [key: string]: any; }, options?: AbstractControlOptions): FormGroup

AND

group(controlsConfig: { [key: string]: any; }, options: { [key: string]: any; }): FormGroup

The 2nd definition is what is deprecated

The difference in this lines is options?: AbstractControlOptions and options: { [key: string]: any; }

To understand why angular is throwing this error we will now consider AbstractControlOptions

interface AbstractControlOptions {   validators?: ValidatorFn | ValidatorFn[] | null   asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null   updateOn?: 'change' | 'blur' | 'submit' } 

We continue to breakdown the problem by noting that the difference between this structure and your structure is ValidatorFn[]

interface ValidatorFn {   (control: AbstractControl): ValidationErrors | null } 

Overally, the error is thrown in your case because your Validator function is expected to take a control and return ValidationErrors | null. In the line validate(control: AbstractControl): void, your code actually returns void but expected to return a ValidationError | null

Solution

From the problem description, the solution is to simply modify the ValidatorFn

Ensure that your ValidatorFn returns a ValidationError or if no error returns null From ValidationErrors defination

type ValidationErrors = {     [key: string]: any; }; 

You will need to return a key value pair object e.g {required_if: true}

We can change your code by adding return statements as expected

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;   } } 
like image 77
Owen Kelvin Avatar answered Sep 19 '22 13:09

Owen Kelvin


I also receive same error, I make following changes.

  • make sure that your validator function signature matches like this. (A function that receives a control and synchronously returns a map of validation errors if present, otherwise null.)

    • function Your_Function_Name(ObjectName: AbstractControl): ValidationErrors | null { }
  • and you can change code in the form builder like this.

    • const formOptions: AbstractControlOptions = { validators: Your_Function_Name };
  • and in the formbuilder object pass above formOptions object like this

    • this.formObject = this.formBuilder.group({ fullName: ['', [Validators.required]] }, formOptions);
like image 28
shrey Avatar answered Sep 19 '22 13:09

shrey