4

I saw there is a topic which looks like mine but it doesn't really answer my problem because we don't manage the errors in the same way. FormBuilder group is deprecated

First of all, I just migrated to Angular 11 and I have this problem now:

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.

In this page I generate automatically many forms on my page and in the case of a date range I use two datepickers. I created a function for checking the values in the 2 date pickers.

Component:

newGroup = this.fb.group(
        {
          [node.type + '_' + node.objectId + '_dateFrom']: [
            '',
            [Validators.required]
          ],
          [node.type + '_' + node.objectId + '_dateTo']: [
            '',
            [Validators.required]
          ]
        },
        {
          validator: CheckFromToDate(
            node.type + '_' + node.objectId + '_dateFrom',
            node.type + '_' + node.objectId + '_dateTo'
          )
        }
      );

Validator:

export function CheckFromToDate(fromName: string, toName: string) {
  return (formGroup: FormGroup) => {
    const from = formGroup.controls[fromName];
    const to = formGroup.controls[toName];
    const dateFrom = new Date(from.value);
    const dateTo = new Date(to.value);
    const today = new Date();
    if (to.errors && from.errors) {
      // return if another validator has already found an error on the matchingControl
      return;
    }
    if (!from.value) {
      from.setErrors({ wrongDate: true });
      to.setErrors(null);
    } else if (!to.value) {
      to.setErrors({ wrongDate: true });
      from.setErrors(null);
    } else if (dateFrom.getTime() < -3600000) {
      from.setErrors({ wrongDate: true });
      to.setErrors(null);
    } else if (dateFrom > today) {
      from.setErrors({ wrongDate: true });
      to.setErrors(null);
    } else if (dateTo.getTime() < -3600000) {
      to.setErrors({ wrongDate: true });
      from.setErrors(null);
    } else if (dateTo > today) {
      to.setErrors({ wrongDate: true });
      from.setErrors(null);
    } else if (dateFrom.getTime() > dateTo.getTime()) {
      from.setErrors({ fromTo: true });
      to.setErrors({ fromTo: true });
    } else {
      from.setErrors(null);
      to.setErrors(null);
    }
  };
}

How can I make my validators work with the new way of handling validators in Angular 11?

2
  • Could you link what you've already found, rather than describing it? Commented Jan 6, 2021 at 11:05
  • Thanks for the remark, i just did it. Commented Jan 6, 2021 at 11:12

2 Answers 2

12

Change your validator signature from

return (formGroup: FormGroup) 

to

return (controls: AbstractControl) 

Then change the way you access the controls from

const from = formGroup.controls[fromName];

to

const from= controls.get(fromName);

Also change the way you report the errors back from

from.setErrors({ wrongDate: true });

to

return from.setErrors({ wrongDate: true }); // note the return statement.

One final change would be to change

newGroup = this.fb.group(
        {
           ...
        },
        {
          validator: CheckFromToDate(
            node.type + '_' + node.objectId + '_dateFrom',
            node.type + '_' + node.objectId + '_dateTo'
          )
        }
      );

to

newGroup = this.fb.group(
        {
           ...
        },
        {
          validator: CheckFromToDate(
            node.type + '_' + node.objectId + '_dateFrom',
            node.type + '_' + node.objectId + '_dateTo'
          )
        } as AbstractControlOptions
      );

Note the casting to AbstractControlOptions and that should remove the deprecated warning.

You can refer the official documentation for a detailed explanation.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! I have to come to this "duplicated" question to solve my problem, the original question's answer doesn't help
as AbstractControlOptions resolved the issue. Thanks!
0

User, a Validators should return or an object (if error) or null (if not error). You souldn't use setError. replace yours from.setErrors and to.setErrors, you can return,e.g. if there're an error an object like

{errorFrom:...,errorTo:...}

So, your validator like

return (formGroup: FormGroup) => {
    ...
    const error={errorFrom:null,errorTo:null}

    if (to.errors && from.errors) {
      // return if another validator has already found an error on the matchingControl
      return null;
    }
    if (!from.value) {
      error.errorFrom="wrong Date from"
    } else if (!to.value) {
      error.errorTo="wrong Date to"
    } else if (dateFrom.getTime() < -3600000) {
      error.errorFrom="wrong Date from"
    } else if (dateFrom > today) {
      error.errorTo="From greater than today"
    } else if (dateTo.getTime() < -3600000) {
      error.errorTo="wrong Date to"
    } else if (dateTo > today) {
      error.errorTo="To greater than today"
    } else if (dateFrom.getTime() > dateTo.getTime()) {
      error.errorTo="from greater than to"
      error.errorFrom="from greater than to"
    }
    //if error.errorTo!=null or error.errorFrom!=null, the error, else null
    return error.errorTo || error.errorFrom? error:null;
  };

and you control as usually

 <span *ngIf="form.get(node.type + '_' + node.objectId + '_dateFrom').errors?.errorFrom>
  {{form.get(node.type + '_' + node.objectId + '_dateFrom').errors.errorFrom}}
 </span>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.