FormBuilder group is deprecated FormBuilder group is deprecated angular angular

FormBuilder group is deprecated


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