42

I was attempting to answer someone elses question. And in doing so realised there was quite a bit of uncertainty in my mind about a few things. I'm hoping someone can provide feedback on the numbered points 1..4:

Task: Conditionally make input field readonly

Relevant section of HTML:

<input type="text" placeholder="Club Name" #clubName>

Add this to Typescript component.

// class properties
@ViewChild('clubName')
inp:HTMLInputElement; // Could also use interface Element

// conditionally set in some other methods of class
inp.setAttribute('readonly', 'readonly');
inp.removeAttribute('readonly');

Have to say this is a grey area for me.

  1. Is referencing HTMLInputElement or Element directly with @ViewChild in Angular 2+ a bad practice? Only, I've often seen examples using ElementRef or chaining off to nativeElement from ElementRef.

Since VS Studio doesn't have Intelli-sense for those, I suddenly feel like I'm coding in the dark. i.e, you never get feedback about methods setAttribute or removeAttribute, their parameter requirements etc. (I'm aware of As to cast too)


  1. Then, after looking at the docs, I suspect you can do this directly on your input in the HTML template:

<input [attr.readonly]= "isReadOnly">

IIRC I think you have to do this way with a property get in Typescript:

get isReadOnly() :boolean {
}

Is this way valid?


  1. I'm wondering, can you do the method syntax too in the HTML template:

<input [attr.readonly]= "isReadOnly()">

Typescript

isReadOnly() :boolean {
}

Is this way valid?


4. In summary, what's the best approach?

Update: There is also *ngIF so you output one of two input elements with same name. But that sounds to me like a sledgehammer to crack a nut.

JGFMK
  • 7,107
  • 4
  • 46
  • 80
  • Define valid.... Because if you're asking if it works then test it and find out. This is a very broad question.... I use `2 & 3` on seperate occasions depending on what I need to compute to determine the bool. – Zze Jul 20 '17 at 22:54

4 Answers4

105

You need to use the following (Angular 4):

<input [readonly]="isReadOnly">

If you use att.readonly then the input will always be read-only because the readonly attribute will be present even if its value is false. By using [readonly] Angular will only place the attribute if isReadOnly is true.

In HTML, the following is sufficient to cause an input to be read-only:

<input readonly>
phn
  • 1,414
  • 1
  • 13
  • 9
4

None of them worked for me.. Finally found solution by creating custom directive angular.. Directives are powerful feature of angular

  1. Create Custom Directive

@Directive({
  selector: '[readonly],[readOnly]',
  host: {
    '[attr.readonly]': '_isReadonly ? "" : null'
  }
})
class ReadonlyDirective {
  _isReadonly = false;

  @Input() set readonly (v) {
     this._isReadonly = coerceBooleanProperty(v);
  };

  ngOnChanges(changes) {
    console.log(changes);
  }
}
  1. Add into module declarations

@NgModule({
  ...
  declarations: [ ..., ReadonlyDirective ],
  ...
})
3. Now its time to use directive as following.

<input [(ngModel)]="name" [readonly]="isReadonly" />
or
<input [(ngModel)]="name" readonly />
Directives are powerful feature of angular, I strongly recommend you to go through https://angular.io/guide/attribute-directives

Demo https://stackblitz.com/edit/angular-readonly-input-aifncy?file=src/app/app.component.ts

BEJGAM SHIVA PRASAD
  • 1,470
  • 1
  • 14
  • 23
3

All depends on what you want to achieve. At first look, I would say that pct. 2 is the simplest way to do it:

<input [attr.readonly]= "isReadOnly">

Then, on your component you declare the variable:

isReadOnly: boolean;

After, you assign the value as you wish:

// when you want to be read-only
isReadOnly = true;
// whe you want to be editable
isReadOnly = false;
BogdanC
  • 2,368
  • 2
  • 21
  • 22
  • If you use `att.readonly` then the input will always be read-only because the `readonly` attribute will be present even if its value is false. By using `[readonly]` Angular will only place the attribute if `isReadOnly` is true. This answer is wrong. Read the accepted answer. – Tushar Khanna Jul 28 '20 at 08:45
1

You can use <input readonly="{{ variable }}>".

In your *.component.ts, initialize the variable:

private variable: boolean = true;
Rodrigo Pauletti
  • 514
  • 2
  • 7
  • 12