Home > Software design >  Controls of controls
Controls of controls

Time:07-13

Currently i am working on validations for my forms with mat-errors and hasErrors, everything is working fine till i need another control for a "inner" formgroup, what i mean is:

prozessPersonenzuordnungenForm = new FormGroup({
    person: new FormGroup({
      firmenbezeichnung: new FormControl(),
      nameC: new FormControl('', [Validators.required]),
      briefanrede: new FormControl('x'),
    }),
  });

I'm trying to reach the person.nameC validation. Im using this function:

public hasError = (controlName: string, errorName: string) => {
    return this.prozessPersonenzuordnungenForm.controls[controlName].hasError(
      errorName
    );
  };

The problem is with this function i only reach the person FormGroup and not the nameC formControl. So i need another "deeper control".

Thats how my html looks like:

<mat-error *ngIf="hasError('nameC', 'required')">Bitte gebe eine Person an!</mat-error>

I also tried it in html with person.nameC, but that was also not working. What would be a good way to reach my inner FormControl with my hasError function?

CodePudding user response:

Since your controls property is an object that has that simplified structure:

controls = {
    person: {
       nameC: {
         hasErrors: err => bool
       }
    }
}

You cannot say controls["person.nameC"] because there's no such property and these dot notations will not be automatically converted into nested property accessing.

This is left purely on your decision how to handle them. One idea is you to parse the dot-separated strings, split them and try to access the object in a loop.

For instance, if you split "person.nameC" string into an array by ., you will receive arr = [ "person", "nameC" ]

So let's examine the algorithm now:

let property = controls;

We start with the property from the furthest point - the whole control object. And one by one we are getting deeply:

property = property[ arr[0] ]

This will evaluate to property = property["person"] which will make the property variable to look like:

property = {
    nameC: {
       hasErrors: err => bool
    }
}

Now you can continue the same way

property = property[ arr[1] ]

Which will evaluate to property = property["nameC"] and the final result will be

property = {
    hasErrors: err => bool
}

Which is the one you want.

Of course, you don't need to manually to that, you can just loop through it:

let property: any = this.prozessPersonenzuordnungenForm.controls;
controlName.split('.').forEach(propertyKey => property = property[propertyKey]);

return property.hasError(errorName);

CodePudding user response:

Thx for your help guys, but i found a much easier way!

Thats my working solution:

public hasError = (controlName: string, deepControlName:string,  errorName: string) => {
    return this.prozessPersonenzuordnungenForm.controls[controlName].get(deepControlName)?.hasError(errorName);
  };

For example, i can use it now like this:

<mat-error *ngIf="hasError('person', 'nameC', 'required')"> </mat-error>  

  • Related