1

We have a Formbuilder with multiple fields. Sometimes, requirements want to toggle certain fields. We can turn them off with If statements validators, and use NgIf in the html. Is there an easy way to toggle multiple fields on a 20 field form, and simplify the syntax?

Is it possible with Formbuilders, or do we have to transfer to form array? Syntax below seems repetitive, curious how it can be simplified,

Currently, have around 20 flag fields.

{
this.customerForm = this.formBuilder.group({
  'firstName': [null, [Validators.maxLength(50), PhoneNumberValidator]],
  'phoneNumber': [null, [Validators.maxLength(50), PhoneNumberValidator]],
  'streetName': [null, [Validators.maxLength(50), PhoneNumberValidator]],

  'emailAddress': [null, [Validators.maxLength(50), Validators.email]],
  'city': [null, [Validators.required, Validators.maxLength(200)]],
  'state': [null, [Validators.maxLength(200)]],
  'zip':[null,[Validators.maxLength(200)]]
});

}

ngOnInit() { 
// this syntax seems repetitive, how to simplify along with NgIf in html?

if (this.firstNameFlag == false) {
  this.customerForm.get('firstName').clearValidators();
  this.customerForm.get('firstName').updateValueAndValidity();
} 

if (this.phoneNumberFlag == false) {
  this.customerForm.get('phoneNumber').clearValidators();
  this.customerForm.get('phoneNumber').updateValueAndValidity();
}
if (this.streetNameFlag == false) {
  this.customerForm.get('streetName').clearValidators();
  this.customerForm.get('streetName').updateValueAndValidity();
}
etc
  • can you provide example? I read about them earlier, not sure how to apply here –  Jan 12 '20 at 08:32

1 Answers1

1

Artportrait, I hate clear and set validators. A FormControl is invalid if is invalid and is enabled, so I think it's better disabled or not

For disabled a formControl we can use a directive -not is valid using [disabled]="variable"-, see this SO answer

For avoid 20 flag fields you can use a simple array. If your array is, e.g.

fields=['firstName','streetName','state','zip']

Yours controls in the form can be (see that you don't use *ngIf else display.none)

<ng-container [style.display]="fields.indexOf('firstName')<0?'none':''"> 
  first name : 
  <input formControlName='firstName'   
      [enabledControl]="fields.indexOf('firstName')>=0?'>
</ng-container>

Another aproach is really create a different formGroup each time. Using the same array we can has a function createForm

createForm(fields)
{
   const form=new FormGroup({});
   if (fields.indexOf('firstName')>=0)
     form.addControl('firstName',new FormControl('', [Validators.maxLength(50), PhoneNumberValidator]]
   if (fields.indexOf('phoneNumber')>=0)
     form.addControl('phoneNumber',new FormControl('', [Validators.maxLength(50), PhoneNumberValidator]]
   ....
   return form
}

And our inputs like

<ng-container *ngIf="fields.indexOf('firstName')>=0" 
  first name : 
  <input formControlName='firstName'>
</ng-container>

the other aproach is create dynamic forms as Plochie say, but is an aproach that add a complex to the app that we need evaluate (in the docs you has a way to do it)

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • hi @Elisio, can you answer this question also? part b of an answer was not working, maybe you can improve it ? thanks https://stackoverflow.com/questions/59505578/angular-iterate-over-reactive-form-controls-and-subchildren-etc?noredirect=1&lq=1 –  Jan 13 '20 at 02:14
  • I will use an array as you mentioned with disabled, this line trying to understand "Yours controls in the form can be (see that you don't use *ngIf else display.none)", are you saying there is no way around wrapping each form input with ngcontainer? i have 20 fields (which I will have to wrap with this), if not, thats fine, your answer is real helpful anyway , isn't it better to use ngIf and remove the dom element completely, rather than disable the view with styles display? –  Jan 13 '20 at 02:31
  • gave thumbs up on your answer –  Jan 13 '20 at 02:32
  • If you use *ngIf -with the option of disabled- the formControl don't disable it. it's the reason of use display:none. Respect the part b), thanks for the advice, must be `this.editSharedForm.get('addressChangeReason').clearValidators()` – Eliseo Jan 13 '20 at 07:30
  • I just transferred to the array, someone asked a question, is there anyway to strongly tie couple the array parameters, with the formbuilder form fields? this way no one can write in incorrect values, curious if its possible, thanks –  Jan 13 '20 at 19:49
  • can we try to incorporate with this link ? https://medium.com/@alvino.aj/type-safety-reactions-with-the-angular-form-builder-6de51e2338fc –  Jan 13 '20 at 20:02
  • or this, https://itnext.io/help-keep-angular-forms-type-safe-ca35f7b2edf8 want to handle array properly –  Jan 13 '20 at 20:03
  • I want to incorporate input array with the interface if possible –  Jan 13 '20 at 20:05