Cannot disable matInput element with [formControlName]
Solution 1
If you are using a FormGroup, then you should not disable the form in the HTML Template. It will not work if you try to disable in HTML together with FormControl. Instead, it should be done within the FormGroup. Try this:
template: `
<mat-form-field [formGroup]="form">
<input matInput placeholder='Name' [formControlName]="formControlName">
</mat-form-field>
`
and:
ngOnInit() {
this.form = this.fb.group({
name: new FormControl({ value: '', disabled: this.disabled })
});
}
Also...not a big deal but..you should really be doing:
public form: FormGroup;
instead of:
public form: any;
Don't forget the import as well
import { FormGroup, FormControl } from '@angular/forms';
Btw, the name inside of the form group declaration should match whatever you have set in the HTML. So:
<input formControlName="myInputName">
and
this.form = this.fb.group({
myInputName....
});
Solution 2
<mat-form-field fxFlex>
<input matInput placeholder="No" formControlName="no" readonly>
</mat-form-field>
Have you tried readonly option. This works fine with me.
Working code: html:
<mat-form-field fxFlex>
<input matInput placeholder="No" formControlName="no" readonly>
</mat-form-field>
Solution 3
I have had the same issue and I have solved it with *ngIf directive. If input should be disabled, make it disabled, remove its form binding and give its value manually. If it's not, than use your formControl as it is.
This is your template:
<mat-form-field [formGroup]="form">
<input matInput placeholder='Name' [formControlName]="formControlName" [disabled]='disabled'>
</mat-form-field>
change it with:
<mat-form-field *ngIf="disabled">
<input matInput placeholder='Name' [value]="form.formControlName" disabled='true'>
</mat-form-field>
<mat-form-field *ngIf="!disabled" [formGroup]="form">
<input matInput placeholder='Name' [formControlName]="formControlName">
</mat-form-field>
Solution 4
-->output try this.
.html file
<form name="fg" [formGroup]="fg" >
<mat-form-field >
<input matInput placeholder="Email" formControlName="email">
</mat-form-field>
</form>
.ts file
import this : import { FormBuilder, FormGroup, Validators } from '@angular/forms';
constructor(private _formBuilder: FormBuilder) { }
this.fg= this._formBuilder.group({
email :[
{
value : '[email protected]',
disabled: true
},
Validators.required
],
Solution 5
If you are using FormGroup you have to use disabled property creating your FormGroup/FormControl:
name: new FormControl({ value: '', disabled: this.disabled })
But if you want to disable/enable you can use this in your HTML:
<input type="text" formControlName="name" [attr.disabled]="isDisabled == true ? true : null" />
![John](https://lh4.googleusercontent.com/-6-yKyG1ZZUI/AAAAAAAAAAI/AAAAAAAAABA/5a7UfitqO5Y/photo.jpg?sz=256)
John
Personal project: rSchedule - typescript library for generating dates for a given recurrence schedule ts-decoders - typescript library for validating unknown inputs and generating nice error messages rx-controls - typescript library, inspired by Angular's ReactiveFormsModule, for simplifying web app forms Angular IsLoadingService - Angular service for tracking loading state of arbitrary data Angular RouterStoreService - Angular service for tracking the Angular router's state Angular SizeObserver - Angular service for applying styles to a DOM element based on it's rendered size in the browser
Updated on July 09, 2022Comments
-
John almost 2 years
I'm using
matInput
andmat-form-field
(@angular/material) in an Angular component, and I can't disable thematInput
.A working example can be seen here.
It seems likely that I'm missing something obvious, but for the life of me I can't figure out what. Is this a bug?
If I remove
[formControlName]
from theCustomFormInputComponent
, then I can successfully disable thematInput
CustomFormInputComponent
:import { Input, Component } from '@angular/core'; import { FormGroup } from '@angular/forms'; @Component({ selector: 'app-custom-form-input', template: ` <mat-form-field [formGroup]="form"> <input matInput placeholder='Name' [formControlName]="formControlName" [disabled]='disabled'> </mat-form-field> `, }) export class CustomFormInputComponent { @Input() form: FormGroup; @Input() formControlName: string = 'name'; @Input() disabled = false; }
AppComponent
:import { Component } from '@angular/core'; import { FormBuilder } from '@angular/forms'; @Component({ selector: 'my-app', template: ` <p>At least one of these inputs should be disabled, but none are :(</p> <app-custom-form-input [form]="form" [disabled]='true'></app-custom-form-input> <app-custom-form-input [form]="form" [disabled]="'disabled'"></app-custom-form-input> `, }) export class AppComponent { public form: any; constructor(private fb: FormBuilder) {} ngOnInit() { this.form = this.fb.group({ name: '' }) } }
Any insights are greatly appreciated!
Answer
For a bit more context on David's answer: Angular updates DOM state based on the disabled status of a reactive form control. What I think is happening: angular is rendering the
CustomFormInputComponent
before theAppComponent
and is rendering the component as disabled. Then the AppComponent is rendered and theform
is built with thename
control enabled. Angular then goes and un-disabled the DOM input element (which is behavior as designed). -
John over 6 yearsOn what are you basing your assertion that "If you are using a FormGroup, then you should not disable the form in the HTML Template"? No where in the reactive form guide is this stated, so far as I can tell. What makes you think the behavior I'm experiencing isn't a bug?
-
John over 6 yearsFor example, multiple
input
elements can bind to the same form control (I think). It's not immediately obvious to me why I couldn't disable one of those inputs in the html, but leave the reactive form control enabled so that the other inputs binding to it still worked. -
David Anthony Acosta over 6 yearsBecause in that same guide, you can clearly see that all the validation on reactive forms is taking place in the class, not in the HTML. Even something as simple as "required" is added in the component class in their examples. No where in their guide is it done in the HTML.... Otherwise why even use reactive forms
-
David Anthony Acosta over 6 yearsI think you are a bit confused about how FormControl, FormGroup work.
-
David Anthony Acosta over 6 yearsAlso, it's not even an assertion. Angular has a built in console warning that basically says "HEY DON'T DO THAT, DO IT IN THE CLASS". Open your console when you attempt to disable an input with formControlName and you will see it. It's pretty clear it's not meant to be disabled in that way.
-
John over 6 yearsWell A) I hadn't noticed that. Thanks! B) "We recommend using this approach to avoid 'changed after checked' errors." Clearly disabling via the DOM is supported, otherwise they would say "you must". Not recommend. But this does seem to explain what's happening. Angular is (probably) rendering the input element as disabled, and then enabling it after that when it builds the parent element.
-
David Anthony Acosta over 6 yearsNo, multiple elements cannot share the same FormControl. Recommended basically means must.For example, it's recommended you encrypt passwords. But it's not a must. Would you then not encrypt them and just say "Well it's recommended, it's not a must...."
-
Tatyana almost 6 years@DavidAnthonyAcosta But if I change this.disabled value to false - my control stays disabled. Is there a way to undisable the control?
-
DeadPassive over 5 years@Tatyana - You can enable/disable form controls programmatically e.g.
this.printForm.controls['title'].enable();
orthis.printForm.controls['title'].disable()
-
yogesh chavan over 4 yearsI have added a working sample but still down vote 🤐.
-
Irrfan23 over 4 yearscopy answer of @yogesh chavan
-
omostan almost 4 yearsI don't understand people voting down this answer. It is one of the most accurate of all the answers besides @N_B answer if you're implementing angular material input. Both answers are the same and worked for me. I wonder why "David Anthony Acosta" anser is the accepted one. In my case, I am implementing *ngxPermissionsOnly and I couldn't combine *ngIf with it because it implements *ngIf under the hood. The solution was to use readonly instead of [disabled]="true". With all that said, I am voting both answers up.
-
Mohamad Al Asmar over 3 yearsHi, I know this is correct, but I have a different case, I want to conditionally disable form controls without losing their values. Example: I am loading some form data and manually filling some fields and I want these fields to become disabled, how do I do that without losing the value from FormGroup? Note that "this.myForm.get('formcontrol').disable();" will remove the value from FormGroup and I don't want it to be disabled initially unless I have a specific case.
-
Coder0997 over 3 yearsdid not know about 'readonly' property, worked for me.
-
Aditya Yada over 3 yearsthanks a lot .I was unable to disable input using attribute . working fine by disabling using the form control name .this.form.get('fcn').disable() .
-
Willie about 3 yearsYogesh thank you. This was a one word fix for code I was already implementing. Much appreciated!
-
Ole over 2 yearsI love this answer. Upvote!!