17
votes

Let's say we have myFormGroup which is initialized via FormBuilder:

this.myFormGroup = this.fb.group(
  {
    field1: ['', SomeValidator1],
    field2: ['', AnotherValidator2],
    field3: [''],
    ...
  }
);

I'm aware that we can disable particular form control, for instance:

fb.control({value: 'my val', disabled: true});

Of course I can use this syntax in my example and mark as disabled every single control in the group. But the form group might have a lot of controls.

So the question - is there any way to disable entire FormGroup/FormArray while creating (not after) it via FormBuilder?

p.s. The reason I'm asking this question is because I need conditionally initialize form group with active or disabled fields for different kind of user privileges.

5
You can iterate all form fields and mark disable/enable fields. - Mukesh Kumar
Of course this is the solution, but I'm looking for another solution - is there a way of doing this at once :) - shohrukh
Just create a utility method and pass formgroup to it. This method will handle enable/disable fields for you. - Mukesh Kumar
It appears that you can do it with a single line of code: this.myFormGroup.disable(). See the Profile Editor in this stackblitz. I don't know if it can be done when creating the group however. - ConnorsFan
Please note that, if you add the line of code just after creation, it is not so different from having an extra option in this.fb.group(...). - ConnorsFan

5 Answers

24
votes

I had same problem, Angular FormBuilder receives, initial state of control, and verify if the param its like to { value: any, disabled: boolean, ..... } if the parameter meets this struct, initialize the control with value and disabled/active.

try:

this.myFormGroup = this.fb.group(
  {
    field1: [{ value: '', disabled: true }, SomeValidator1],
    field2: [{ value:'', disabled: true }, AnotherValidator2],
    field3: [{ value:'', disabled: true}],
    ...
  }
);
2
votes

Try this code:

enableForm(group: FormGroup, enable:boolean) {
   for (const i in group.controls) {
      if(enable) {
        group.controls[i].enable();
      } else {
        group.controls[i].disable();
      }
   }
}
2
votes

I didn't find any better solution than just disable the group right after its creation.

// original code
this.myFormGroup = this.fb.group({
  field1: ['', SomeValidator1],
  field2: ['', AnotherValidator2],
  field3: [''],
  ...
});
// added
this.myFormGroup.disable();

This solution is better than Luis Felipe Diaz Valbuena's, because you don't need to { disable: true } each field. Imagine doing this for 10+ fields.

1
votes

Also you may try this to dynamic disable and enable form control

this.contactInfo = this.fb.group({
      email: ['', Validators.required],
      phone: ['', Validators.required]
    });
//disable form: only phone control
this.contactInfo.get('phone').disable();

//enable form :phone control
this.contactInfo.get('phone').enable();
1
votes

We can create an extension for AbstractControl

import {AbstractControl} from '@angular/forms';

declare module '@angular/forms' {
  interface AbstractControl {
    markAsDisabled(disable: boolean, onlySelf?: boolean): void;
    markAllAsDisabled(disable: boolean, onlySelf?: boolean): void;
  }
}

function markAsDisabled(disable: boolean, onlySelf?: boolean): void {
  if (disable) {
    this.disable();
  } else {
    this.enable();
  }

  if (this._parent && !onlySelf) {
    this._parent.markAsDisabled(disable, onlySelf);
  }
}

function markAllAsDisabled(disable: boolean, onlySelf?: boolean): void {
  this.markAsDisabled(disable, onlySelf);

  Object.keys(this.controls).forEach(k => {
    (this.controls[k] as AbstractControl).markAsDisabled(disable, onlySelf);
  });
}

AbstractControl.prototype.markAsDisabled = markAsDisabled;
AbstractControl.prototype.markAllAsDisabled = markAllAsDisabled;

then just call

// Diabled
this.myFormGroup.markAllAsDisabled(true);

// Enabled
this.myFormGroup.markAllAsDisabled(false);

DEMO