58

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
  • 5,820
  • 9
  • 32
  • 50
  • 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
  • 5
    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

7 Answers7

54

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,241
  • 5
  • 30
  • 48
ErvTheDev
  • 4,117
  • 2
  • 15
  • 19
  • 25
    disabling control in formControl leads to null value. – NaN May 25 '18 at 17:38
  • 5
    @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
  • 2
    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
44

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
  • 97,176
  • 43
  • 357
  • 461
Silambarasan R.D
  • 1,176
  • 13
  • 20
  • 14
    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.D 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
21

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" />

Steve
  • 490
  • 2
  • 18
5

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,373
  • 2
  • 15
  • 30
5

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()
}
WasiF
  • 21,437
  • 14
  • 108
  • 114
2

If using form builder, with reactive forms:

this.customerForm = this.formBuilder.group({
      customerName: [{value: null, disabled: true}, Validators.required],
})
james ace
  • 1,693
  • 18
  • 10
0

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" />

this works with input and textarea at least.

user1767316
  • 2,887
  • 3
  • 32
  • 44
  • 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