'Conditionally make input field readonly in Angular 2 or 4: Advice + Best/which way to do it
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.
- Is referencing
HTMLInputElement
orElement
directly with@ViewChild
in Angular 2+ a bad practice? Only, I've often seen examples usingElementRef
or chaining off tonativeElement
fromElementRef
.
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)
- 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?
- 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.
Solution 1:[1]
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>
Solution 2:[2]
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;
Solution 3:[3]
None of them worked for me.. Finally found solution by creating custom directive angular.. Directives are powerful feature of angular
- 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);
}
}
- Add into module declarations
@NgModule({
...
declarations: [ ..., ReadonlyDirective ],
...
})
<input [(ngModel)]="name" [readonly]="isReadonly" />
or
<input [(ngModel)]="name" readonly />
Demo https://stackblitz.com/edit/angular-readonly-input-aifncy?file=src/app/app.component.ts
Solution 4:[4]
You can use <input readonly="{{ variable }}>"
.
In your *.component.ts, initialize the variable:
private variable: boolean = true;
Solution 5:[5]
i have fixed it :)
<input matInput type="text" (focus)="userNameFocus()" placeholder="Username" #u1 formControlName="userName" autocomplete="off" />
// initialize form on userName focus
<input matInput [type]="inputType" style="-webkit-text-security: square;" #p2 formControlName="password" />
Solution 6:[6]
There is a more simple solution, just use
@Input('readonly') readonly: boolean
ngOnInit(){
this.readonly= this.readonly!== undefined && this.readonly!== false
}
now the readonly attr on your component will be
false:
<app-component>
<app-component [readonly]='false'>
true:
<app-component readonly>
<app-component [readonly]='true'>
Solution 7:[7]
component.html
<input matInput formControlName="status" [readonly]="!status" />
component.ts
// when you want to be read-only
isReadOnly = true;
// whe you want to be editable
isReadOnly = false;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | phn |
Solution 2 | BogdanC |
Solution 3 | |
Solution 4 | Rodrigo Pauletti |
Solution 5 | ahuemmer |
Solution 6 | David M. |
Solution 7 | Sushil |