68

How to make a formControl in angular readonly

I know i can do it in html like

<input type="text" formControlName="xyz" readonly />

how to do it from JS Code and not html i.e in a model driven way

Ankit Raonka
  • 6,429
  • 10
  • 35
  • 54
  • 9
    You can set **disabled** by `this.form.controls.name.disable({onlySelf: true});`, but I didn't find anything for `readonly` so far. – Pengyy Aug 02 '17 at 05:51
  • 6
    and here is a relevent issue: https://github.com/angular/angular/issues/11447, seems it's not provided right now. – Pengyy Aug 02 '17 at 06:04

6 Answers6

58

If you are using Reactive Forms you can assign it dynamically like in the example code below (email field)

    this.registerForm = this.formBuilder.group({
          first_name: ['', Validators.required],
          last_name: ['', Validators.required],
          email: new FormControl({value: null, disabled: true}, Validators.required),
          password: ['', Validators.compose([Validators.required, Validators.email])],
          confirm_password: ['', Validators.required],
    });

If you want to get all the values including disabled controls you should use:

    this.registerForm.getRawValue();

View method comment on source code

    /**
       * 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.
       */
      getRawValue(): any;

Enjoy coding!

Collin Barrett
  • 2,441
  • 5
  • 32
  • 53
ErvTheDev
  • 4,390
  • 3
  • 16
  • 20
  • 30
    disabling control in formControl leads to null value. – NaN May 25 '18 at 17:38
  • 7
    @PSyLoCKe If you want to get all the values including disabled controls you should use: this.registerForm.getRawValue(); – ErvTheDev Aug 27 '18 at 15:06
  • 3
    I don't understand why this was used as the accepted answer... as PSyLoCKe noticed above - getRawValue() will NOT fetch the disabled values. They still come as NULL even if you try getRawValue(). – tom33pr Nov 26 '18 at 12:56
  • @tom33pr to avoid confusion please always consult official docs. /** * 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. */ getRawValue(): any; – ErvTheDev Nov 26 '18 at 14:24
  • @PleaseDontBullyMe If you want to get all the values including disabled controls you should use: this.registerForm.getRawValue(); #stoptobulling haha :) – ErvTheDev Dec 03 '18 at 14:08
  • Disabling the field does not allow text selection – Charles Robertson Jan 28 '19 at 17:14
  • getRawValue() does work for me. However this isn't perfect as it would grab all values from all disabled controls. – Adam Marshall Sep 27 '19 at 14:07
50

In my guess there is no use of READONLY in a Reactive Form (Angular 2+).

In a normal HTML, CSS based project

We use READONLY attribute to prevent user from type/select the form control but we get value from the input.

We use DISABLED attribute to prevent user from type/select the form control and we dont get value from the input.

In an Angular 2+ CLI based Projects

We don't need READONLY attribute to prevent user from type/select. Because DISABLED attribute is enough to prevent user from type/select and also you can get value from the disabled input/select/checkbox/radio field.

You can add disabled attribute to the field in model-driven way

While creating FormGroup

this.formGroupName = this.fb.group({
    xyz: [{ value: '', disabled: true }, Validators.required]
});

At Runtime

this.formGroupName.get('xyz').disable({ onlySelf: true });

Getting values from FormGroup (Edited)

To get values from not disabled fields only

this.formGroupName.value;

To get values of all fields in the FormGroup

this.formGroupName.getRawValue();

So here you don't need the READONLY attribute. Hope it helps.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Silambarasan R
  • 1,346
  • 15
  • 22
  • 20
    The problem with disabled fields (in reactive forms) is that they don't pass the validation. The unique way I found was using readonly. – Eric Mar 10 '19 at 23:40
  • @Eric There is no use of Validation for Disabled inputs. Brief more about your use of code. – Silambarasan R Mar 11 '19 at 07:57
  • 1
    this did the work, I wanted to disable the input. `disabled: true` did not work in my case but `disable({ onlySelf: true });` – Extreme Mar 24 '19 at 17:53
  • 7
    This makes the field disabled, not readonly. So CSS styling is not correct. – Steve Aug 13 '20 at 17:25
  • @Eric disabled controls pass the validation, but you have to check the validation against "form.control.invalid", instead of "form.control.valid". – niio Sep 05 '22 at 09:40
  • @SilambarasanR its not about validating disabled fields, but about supressing user changes eg for the time of background processing or something - at this point, disabling input to prevent input can result in form.valid potentially switching to true. – Antoniossss Jun 16 '23 at 08:27
  • @Antoniossss In that case, you can add a full-screen spinner or you can display a transparent div above the form. – Silambarasan R Jun 16 '23 at 09:14
  • Nah, I dont have freedom on that. Readonly input however is the solution so there is as rationale to have such mode in reactive forms. – Antoniossss Jun 16 '23 at 09:52
  • Ok @Antoniossss I think, you can do like this. After submitting check the form whether it is valid or not then disable the inputs & proceed only if valid. otherwise, you can display errors as you wish. Hope this would help in your case. :) – Silambarasan R Jun 16 '23 at 10:16
  • There are workardounds, but why not have straight ways? Look how you try to proove that it is not needed by proposing workarounds to this missing bit. Having this way of thoughs I could say that I dont need ReactiveForms at all since I can use ngModel and have [disabled] there right? As an abstract, it would be probably handy to be able to set custom flags/attributes to the FormControl and use them (somehow) in the templates - and be able to set [disable] is just one of them – Antoniossss Jun 16 '23 at 10:58
23

We can use any html attribute and bind it in angular using [].

So,you can use attribute binding for the attribute readonly in that control

e.g

<input type="text" formControlName="xyz" [readonly]="anyBooleanPropertyFromComponent" />

Faizal Shap
  • 1,680
  • 1
  • 11
  • 26
4

For the reactive-forms, if you want to make the fields readonly, one way to do so would be to do with plain old javascript using:

(document.getElementById('abc') as HTMLInputElement).setAttribute('readonly','true');

In addition to this, you can convert the code to more typescript and angular way. Use @ViewChild to access the element and then set the readonly property to true:

HTML

<input [formControl]='data' id='abc' #element [readonly]="data.disabled"/>

TS

@ViewChild('element',{static:true, read: ElementRef}) element : ElementRef ;
(this.element.nativeElement as HTMLInputElement).readOnly = true;

However, you will need to check for the status of the formControl before modifying the readonly property.

Sachin Gupta
  • 4,981
  • 3
  • 16
  • 32
2

A simple solution is to set the formcontrol as not disabled:

this._formBuilder.group({
            some: new FormControl(
              {
                value: parseInt(this.myobject.subObject.stringMember),
                disabled: false
              },
              Validators.required
            ),

and, at the same time, to set the <input> and/or <textarea> as readonly:

  • textarea:
  <label>
    <span class="label">SomeLabel</span>
    <textarea
      maxlength="500"
      formControlName="some"
      readonly>
    </textarea>
  </label>
  • input:
<input type="text" formControlName="name" readonly/>

this works with input and textarea at least.

Quentame
  • 254
  • 1
  • 4
  • 13
user1767316
  • 3,276
  • 3
  • 37
  • 46
  • Even if it isn't a best practice, I think this could be used in some situations. Thanks for sharing! – Dario Vogogna Oct 01 '20 at 09:59
  • Thanks, @DarioVogogna my answer was first downvoted because I was also showing what could be some bad practices that I now have removed ;-) – user1767316 Oct 01 '20 at 12:24
2

Manually set formcontrol as disabled

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

Programmatically enable / disable

<button (click)="enable()">Enable</button>
<button (click)="disable()">Disable</button>

disable() {
   this.control.disable()
}

enable() {
   this.control.enable()
}

Get value from disabled FormControl / FormGroup

this.control.getRawValue() // FormControl
this.form.getRawValue() // FormGroup
WasiF
  • 26,101
  • 16
  • 120
  • 128