Create disabled form group with FormBuilder
Asked Answered
C

6

38

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.

Concussion answered 21/8, 2018 at 15:22 Comment(6)
You can iterate all form fields and mark disable/enable fields.Fayola
Of course this is the solution, but I'm looking for another solution - is there a way of doing this at once :)Concussion
Just create a utility method and pass formgroup to it. This method will handle enable/disable fields for you.Fayola
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.Dabney
thnx, neither do I :)Concussion
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(...).Dabney
G
48

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}],
    ...
  }
);
Goss answered 17/6, 2019 at 21:6 Comment(2)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Ingrown
This is totally awesomeness overloaded, this resolved lot of hurdles for me, Thank you so much.Sicular
D
5

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.

Doorsill answered 4/9, 2020 at 10:32 Comment(1)
We're programmers, if you really needed to do this for many fields, a premade value or method could be used instead (e.g. getVal() => ({value:'', disabled: true});). There are OTHER reasons for controlling it on the group level, but typing isn't one of them.Sandie
F
2

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();
      }
   }
}
Fayola answered 21/8, 2018 at 15:30 Comment(1)
While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.Ingrown
P
1

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();
Pongee answered 6/8, 2019 at 13:8 Comment(0)
C
1

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

Conlon answered 27/10, 2020 at 12:38 Comment(0)
F
-1

Angular >= 14 (It's easy to write the code for the lower versions)

I do it like this:

//...
export class MyComponent {
  //...
  myFormGroup = (
    () => {
        let formGroup = this.fb.group({
            field1: this.fb.control<string | null>('', { validators: SomeValidator1 }),
            field2: this.fb.control<string | null>('', { validators: AnotherValidator2 }),
            //...
        });
        formGroup.disable();
        return formGroup;
    }
    )();
  //...
}
Fetish answered 24/3 at 21:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.