56

I have a reactive form. On edit I want a control disabled.

The below works:

   this.myForm.controls['analysis_horizon'].disable();

However, the key analysis_horizon is no longer in my myForm.value hash.

How do I disable a field with a reactive form but keeping the value in the form values hash?

I tried [disabled]= but I get the below:

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.

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

I load data from my database on edit into the form controls but I need one field to not be allowed to change.

jonrsharpe
  • 107,083
  • 22
  • 201
  • 376
Tampa
  • 69,424
  • 111
  • 266
  • 409
  • it tells you to use disabled attribute directly in HTML, rather than using it with formcontrol. – micronyks Feb 11 '17 at 20:14
  • Given that it's not changing, you could put it back into the value yourself for whatever is consuming it, with `Object.assign` or something. – jonrsharpe Feb 11 '17 at 20:20
  • Maybe I'm misunderstanding but, why not do like the message suggests: `yourFormControl: new FormControl({value: yourPresetValue, disabled: true})` – AT82 Feb 11 '17 at 20:22
  • Possible duplicate of [Angular 2 disabled controls do not get included in the form.value](https://stackoverflow.com/questions/40148102/angular-2-disabled-controls-do-not-get-included-in-the-form-value) – rmcsharry Nov 14 '18 at 08:46
  • 1
    I know this is old now, but reactive forms has another method that's called form.getRawValue() that would do this for you I cant say it works 100% of the time but it works when you use any of the setValue or patch Value methods – Pari Baker May 24 '19 at 01:14
  • Angular 11 getRawValue() doesn't include disabled controls even if using patchvalue. – thinkOfaNumber Mar 29 '21 at 06:34

5 Answers5

128

You could use getRawValue() instead of the value property. According to the documentation:

The aggregate value of the FormGroup, including any disabled controls.

If you'd like to include all values regardless of disabled status, use this method. Otherwise, the value property is the best way to get the value of the group.

this.myForm.getRawValue()
I. Ajeneza
  • 1,318
  • 1
  • 7
  • 7
10

My solution is using [attr.disabled]:

<select formControlName="foo"
  [attr.disabled]="disabled == true ? true : null"> 
</select>

Assuming you have a disabled property in your component. You have to retun null not false to enable the input.

pogiaron
  • 292
  • 3
  • 5
  • 3
    Eventhough no warning is raised by Angular in this case, it still makes the application vulnerable to 'changed after checked' errors. – Nino Filiu Aug 30 '18 at 14:14
7

Here is another option if you don't want to use getRawValue which changes the normal way of getting the value from forms. More reasons why I like readonly better: https://stackoverflow.com/a/7730719/1678151.

My solution also shows how to fill a form control.

component.ts

fillForm(data: any){
 if (data != null && data.firstName){
   this.form.patchValue({
     firstName: data.firstName
   })    
   this.firstNameIsReadOnly = true;
 } 

template.html

<input formControlName="firstName" [readonly]='firstNameIsReadOnly'>

styles.scss

input[readonly] {
 color: rgba(0,0,0,.38);
}
Anthony
  • 2,182
  • 6
  • 39
  • 63
3

Try add onlySelf: true inside method disable:

this.myForm.controls['analysis_horizon'].disable({onlySelf: true});
garfbradaz
  • 3,324
  • 7
  • 39
  • 66
1

I came across this problem whilst trying to implement the Angular Material Datepicker with a reactive form - I wanted the input to be disabled so only the picker can set the date, however Angular shouts at you when you use the disabled attribute in the template, and then removes the value from the form when you do it in the component form group code.

The solution I came up with is to use CSS to prevent interaction with the input:

.disable-pointer-events {
   pointer-events: none;
}
<input
  class="disable-pointer-events"
  formControlName="yourControlName"
/>