300

I already tried to follow the example of other answers from here and I did not succeed!

I created a reactive form (ie, dynamic) and I want to disable some fields at any given time. My form code:

this.form = this._fb.group({
  name: ['', Validators.required],
  options: this._fb.array([])
});

const control = <FormArray>this.form.controls['options'];
control.push(this._fb.group({
  value: ['']
}));

my html:

<div class='row' formArrayName="options">
  <div *ngFor="let opt of form.controls.options.controls; let i=index">
    <div [formGroupName]="i">
      <select formArrayName="value">
        <option></option>
        <option>{{ opt.controls.value }}</option>
      </select>
    </div>
  </div>
</div>

I reduced the code to facilitate. I want to disable the field of type select. I tried to do the following:

form = new FormGroup({
  first: new FormControl({value: '', disabled: true}, Validators.required),
});

not working! Does anyone have a suggestion?

4
  • How could the select be disabled, when you are trying to disable some formcontrol called first?`:) Commented Mar 16, 2017 at 19:47
  • It was just typo. I want to disable select. Can you help me? Commented Mar 16, 2017 at 22:03
  • Could you reproduce a plunker? Commented Mar 17, 2017 at 18:51
  • Are you trying to disable the whole select? And value is not a formArray, it's a formControlName. If you want value to be a formArray you would have to change it. Currently it's a formControlName. So if you want the whole select field to be disabled, just change <select formArrayName="value"> to <select formControlName="value"> Commented Mar 17, 2017 at 19:23

25 Answers 25

562
name: [{value: '', disabled: true}, Validators.required],
name: [{value: '', disabled: this.isDisabled}, Validators.required],

or

this.form.controls['name'].disable();
Sign up to request clarification or add additional context in comments.

6 Comments

if I set a value like that -> country: [ { value: this.address.country, disabled: true } ] the value do not fill
I have used the same technique to disable fields that were auto filled from trusted sources. I have a switch to enable/disable the form, and after enabling the whole form, I usually disable those fields using if statements. After the form is submitted, entire form is disabled once again.
As @retr0 said, typically you would have to enable them right before you consume the entire form for, say, submit the data to the back-end, so there is no chance that the user can enter any data from the moment you enable them and the moment you send the data out of the component.
I want set null for value and also disable. How to do it? I used `` this.form.patchvalue({ dropDown: [{value: null , disbaled: true}] }); `` But it doesnt disable but value set null. Any idea
there is a this.form.get(controlName) function which can be used in nested form as well by joining the path with . so nestedForm.nestedControl and do need to go trough controls :)
|
152

Pay attention

If you are creating a form using a variable for condition and trying to change it later it will not work, i.e. the form will not change.

For example

this.isDisabled = true;
    
this.cardForm = this.fb.group({
    number: {value: null, disabled: this.isDisabled},
});

and if you change the variable

this.isDisabled = false;

the form will not change. You should use

this.cardForm.get('number').disable();

BTW.

You should use patchValue method for changing value:

this.cardForm.patchValue({
    number: '1703'
});

4 Comments

I faced the same problem, do you know why it is not working with variable?
@HarshadVekariya because you do not pass variable but just its value which is evaluated right inside constructor of abstractControl...
Thanks! I was trying to find documentation for this but I couldn't, where does it say we need to pass it in this form? {value: null, disabled: this.isDisabled}
Here's some details to what @Filip Kováč said. It has nothing to do with Angular, because it is basic behaviour of assigning literal value and storing it. Let's simplify example to plain JS to illustrate it: this.a = true; let b = this.a; this.a = false; console.log(this.a); // false console.log(b); // true In this example, variable b got literal value false and maintains no reference to this.a which has provided this literal.
69

I solved it by wrapping my input object with its label in a field set: The fieldset should have the disabled property binded to the boolean

 <fieldset [disabled]="isAnonymous">
    <label class="control-label" for="firstName">FirstName</label>
    <input class="form-control" id="firstName" type="text" formControlName="firstName" />
 </fieldset>

7 Comments

wasted a lot of time figuring out how to disable controls in reactive forms, LOL! this worked .. no directives or extra code needed. cheers 🍻
How is this not the accepted answer?? So much easier than anything else on here.
This is an excellent answer!!! I voted for you, hope you come out on top.
This is the only answer that worked for me in the case of nested form groups with checkboxes. Thank you!
I am using [attr.disabled]="true" on the input field
|
45

It is bad practice to use disable in a DOM with reactive forms. You can set this option in your FormControl, when you init the from

username: new FormControl(
  {
    value: this.modelUser.Email,
    disabled: true
  },
  [
    Validators.required,
    Validators.minLength(3),
    Validators.maxLength(99)
  ]
);

Property value is not necessary

Or you can get your form control with get('control_name')and set disable

this.userForm.get('username').disable();

3 Comments

Why is it a bad practice to use disable in the DOM with reactive forms?
You will get a warning from angular. It looks like you’re using the disabled attribute with a reactive form directive. If you set disabled to true when you set up this control in your component class, the disabled attribute will actually be set in the DOM for you. We recommend using this approach to avoid ‘changed after checked’ errors. So the recommended way to change the disable/enable state directly via controls. Also, you can check this great topic netbasal.com/…
@pumpkinthehead Because in reactive forms, the FormGroup is the Source of Truth, in template driven forms, the template is the Source of Truth.
31

The disabling FormControl prevents it to be present in a form while saving. You can just set it the readonly property.

And you can achieve it this way :

HTML :

<select formArrayName="value" [readonly] = "disableSelect">

TypeScript :

this.disableSelect = true;

Details here

1 Comment

You can use form.getRawValue() to include the disabled controls values
30
this.form.enable()
this.form.disable()

Or formcontrol 'first'

this.form.get('first').enable()
this.form.get('first').disable()

You can set disable or enable on initial set.

 first: new FormControl({disabled: true}, Validators.required)

1 Comment

worked for me. Here is how to put the value in the control at same time. new FormControl({ value: XXX, disabled: true })
12

A more general approach would be.

// Variable/Flag declare
public formDisabled = false;

// Form init
this.form = new FormGroup({
  name: new FormControl({value: '', disabled: this.formDisabled}, 
    Validators.required),
 });

// Enable/disable form control
public toggleFormState() {
    this.formDisabled = !this.formDisabled;
    const state = this.formDisabled ? 'disable' : 'enable';

    Object.keys(this.form.controls).forEach((controlName) => {
        this.form.controls[controlName][state](); // disables/enables each form control based on 'this.formDisabled'
    });
}

Comments

9

If you want to disable first(formcontrol) then you can use below statement.

this.form.first.disable();

Comments

9

Providing disabled property as true inside FormControl surely disables the input field.

this.form=this.fb.group({
  FirstName:[{value:'first name', disabled:true}],
  LastValue:['last name,[Validators.required]]
})

The above example will disable the FirstName input field.

But real problem arises when you try to access disabled field value through form like this console.log(this.form.value.FirstName); and it shows as undefined instead of printing field's actual value. So, to access disabled field's value, one must use getRawValue() method provided by Reactive Forms. i.e. console.log(this.form.getRawValue().FirstName); would print the actual value of form field and not undefined.

1 Comment

getRawValue() - wow, I mean where is this in the docs. Thanks man - this did it for me. I needed to disable the input cause it has prefilled values. I want to pass them into the api params. I could not access them until I used getRawValue() - thanks!
8

If to use disabled form input elements (like suggested in correct answer how to disable input) validation for them will be also disabled, take attention for that!

(And if you are using on submit button like [disabled]="!form.valid"it will exclude your field from validation)

enter image description here

1 Comment

How can you validate for fields that are initially disabled but are set dynamically?
4

This worked for me: this.form.get('first').disable({onlySelf: true});

Comments

4

The best solution is here:

https://netbasal.com/disabling-form-controls-when-working-with-reactive-forms-in-angular-549dd7b42110

Outline of solution (in case of broken link):

(1) Create a directive

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

@Directive({selector: '[disableControl]'})
export class DisableControlDirective {

  @Input() set disableControl( condition : boolean ) {
    const action = condition ? 'disable' : 'enable';
    this.ngControl.control[action]();
  }

  constructor( private ngControl : NgControl ) {}
}

(2) Use it like so

<input [formControl]="formControl" [disableControl]="condition">

(3) Since disabled inputs do not show in form.value on submit you may need to use the following instead (if required):

onSubmit(form) {
  const formValue = form.getRawValue() // gets form.value including disabled controls
  console.log(formValue)
}

1 Comment

I tried this way. I'm showing most of my FormControls after pulling API data, so after setting/patching value to my formControl using this.form.get('FIELD_NAME').patchValue(DYNAMIC_VALUE) I show the formControl. when it passed to directive, it shows Cannot read property 'disable' of undefined
4

I am just using

<input type="text" formControlName="firstName" [attr.disabled]="true || null" />

With this firstName stays accessible in form.value

Important: You have to use || null as the default value, so that angular can remove the attribute alltogether.

Comments

2

enter image description here

lastName: new FormControl({value: '', disabled: true}, Validators.compose([Validators.required])),

Comments

1

If you have a form group, just display the form group. Then all formcontrols are disabled.

formGroup = new FormGroup({
     firstName: new FormControl(''),
     lastName: new FormControl(''),
});
this.formGroup.disable();

Comments

1

I was trying to get values from the localstorage and I wanted the email and password fields to be disabled. This worked for me:

email: new FormControl({value: localStorage.getItem("email"), disabled:true},[
      Validators.required,
      Validators.minLength(3),
    ]),
password: new FormControl({value: localStorage.getItem("password"), disabled:true},[
      Validators.required,
      Validators.minLength(3),
    ])

Comments

1

You can also use attr.disabled for checkbox or radio in html without coding in .ts file, like this:

<input type="checkbox" id="hasDataACheck" formControlName="hasDataA" />
<label class="form-check-label" for="hasDataACheck">
    has Data A
</label>

<input type="text" formControlName="controlA" [attr.disabled]="
  form.get('hasDataA').value ? null : '' />

2 Comments

this will not work if you have dynamic rows / controls in form array. It only applied to first control.
@ArslanAmeer thanks, I will check it and edit if need
0

I had the same problem, but calling this.form.controls['name'].disable() did not fixed it because I was reloading my view (using router.navigate()).

In my case I had to reset my form before reloading:

this.form = undefined; this.router.navigate([path]);

Comments

0

You can declare a function to enable/disable all of the form control:

  toggleDisableFormControl(value: Boolean, exclude = []) {
    const state = value ? 'disable' : 'enable';
    Object.keys(this.profileForm.controls).forEach((controlName) => {
      if (!exclude.includes(controlName))
        this.profileForm.controls[controlName][state]();
    });
  }

and use it like this

// disbale all field but email
this.toggleDisableFormControl(true, ['email']);

Comments

0

Angular 14+

field = new FormControl<any>()

readonly formGroup = new FormGroup<any>({
    field2: new FormControl<any>(),
});

Option 1

 ngOnInit() {
    # ...
    this.field.setDisable();
    this.field.setEnable();
    this.formGroup.controls.field2.setEnable();
    this.formGroup.controls.field2.setDisabled();
    # ...
}

Option 2

private setFieldEnabled() {
    this.field.setEnable()
  }

private setFieldDisabled() {
    this.field.setDisable()
  }

private setField2Enabled() {
    this.formGroup.controls.breakdown.setEnable();
  }

private setField2Disabled() {
    this.formGroup.controls.breakdown.setDisable();
  } 

setEnableOrDisableFields(truth: boolean): void {
    if (truth) {
        this.setFieldEnabled()
        this.setField2Enabled();
        return
    }
    this.setFieldDisabled()
    this.setField2Disabled();
}

Comments

0

You cannot disable the input control using disabled attribute in the reactive forms. The best solution for this is you can simply add a fieldset element and insert the input control in the fieldset element. After that you can easily disable or enable the fieldset element using typescript.

For ex.

index.html

<fieldset [disabled]="variable_name">
    <input name="name" formcontrolname="name">
</fieldset

index.ts

 variable_name:boolean;

 if(condition):
 {
     variable_name=true;
 }
 else
  {
     variable_name=false;
  }

This would easily help you to dynamically hide or show the input control

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

this is how to disable a reactive form

// Function to disable all form controls
disableForm() {
  Object.keys(this.form.controls).forEach(controlName => {
    this.form.get(controlName)?.disable();
  });
}

// Calling the function to disable the form controls
this.disableForm();

1 Comment

While loop thru all field, if you can do all at once?
-1

To make a field disable and enable of reactive form angular 2+

1.To disable

  • Add [attr.disabled]="true" to input.

<input class="form-control" name="Firstname" formControlName="firstname" [attr.disabled]="true">

To enable

export class InformationSectionComponent {
formname = this.formbuilder.group({
firstname: ['']
});
}

Enable whole form

this.formname.enable();

Enable particular field alone

this.formname.controls.firstname.enable();

same for disable, replace enable() with disable().

This Works fine. Comment for queries.

Comments

-1

while making ReactiveForm:[define properety disbaled in FormControl]

 'fieldName'= new FormControl({value:null,disabled:true})

html:

 <input type="text" aria-label="billNo" class="form-control" formControlName='fieldName'>

1 Comment

This just adds the same answer as the accepted one. It adds no new value here.
-4

you can do it easily by adding a css class and bind it to with angular.

.disable{
    pointer-events: none;
}
    <div [ngClass]="{'disable': //condition goes here">
     <input type="text" formControlName="test">
     </div>

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.