Reactive forms - disabled attribute

AngularTypescript

Angular Problem Overview


I am trying to use the disabled attribute from a formControl. When I put it in the template, it works:

<md-input formControlName="id" placeholder="ID" [disabled]="true"></md-input>

But the browser alerts me:

> It looks like you're using the disabled attribute with a reactive form > directive. If you set disabled to true > when you set up this control in your component class, the disabled attribute will actually be set in the DOM for > you. We recommend using this approach to avoid 'changed after checked' errors. >
> Example: > form = new FormGroup({ > first: new FormControl({value: 'Nancy', disabled: true}, Validators.required), > last: new FormControl('Drew', Validators.required) > });

So I put it in the FormControl, and deleted from the template:

constructor(private itemsService: ItemsService) {
    this._items = [];
    this.myForm = new FormGroup({
        id: new FormControl({value: '', disabled: true}, Validators.required),
        title: new FormControl(),
        description: new FormControl()
    });
    this.id = this.myForm.controls['id'];
    this.title = this.myForm.controls['title'];
    this.description = this.myForm.controls['description'];
    this.id.patchValue(this._items.length);
}

But it does not work (it is not disabling the input). What is the problem?

Angular Solutions


Solution 1 - Angular

I have been using [attr.disabled] because I still like this template driven than programmatic enable()/disable() as it is superior IMO.

Change

<md-input formControlName="id" placeholder="ID" [disabled]="true"></md-input>

to

<md-input formControlName="id" placeholder="ID" [attr.disabled]="true"></md-input>

If you are on newer material change md-input to mat-input.

Solution 2 - Angular

In my case with Angular 8. I wanted to toggle enable/disable of the input depending on the condition.

[attr.disabled] didn't work for me so here is my solution.

I removed [attr.disabled] from HTML and in the component function performed this check:

if (condition) {
    this.form.controls.myField.disable();
} else {
    this.form.controls.myField.enable();
}

Solution 3 - Angular

You can enable/disable a form control by using the following methods:

control.disable() or control.enable()

If that did not work for you can use a directive

import { NgControl } from '@angular/forms';

@Directive({
  selector: '[disableControl]'
})
export class DisableControlDirective {

  @Input() set disableControl( condition : boolean ) {
    const action = condition ? 'disable' : 'enable';
    this.ngControl.control[action]();
  }

  constructor( private ngControl : NgControl ) {
  }

}

Then you could use it like this

<input [formControl]="formControl" [disableControl]="disable">
<button (click)="disable = true">Disable</button>
<button (click)="disable = false">Enable</button>

This technique is described here:

https://netbasal.com/disabling-form-controls-when-working-with-reactive-forms-in-angular-549dd7b42110

Hope it helps

Solution 4 - Angular

I found that I needed to have a default value, even if it was an empty string. So this:

this.registerForm('someName', {
  firstName: new FormControl({disabled: true}),
});

...had to become this:

this.registerForm('someName', {
  firstName: new FormControl({value: '', disabled: true}),
});

See my question (which I don't believe is a duplicate): https://stackoverflow.com/questions/49200258/passing-disabled-in-form-state-object-to-formcontrol-constructor-doesnt-work

Solution 5 - Angular

this.form.disable()
this.form.enable()

For one formcontrol makes disable

this.form.get('first').disable()
this.form.get('first').enable()

Or initial set method.

first: new FormControl({disabled: true}, Validators.required)

Solution 6 - Angular

Initialization (component) using:

public selector = new FormControl({value: '', disabled: true});

Then instead of using (template):

<ngx-select
[multiple]="true"
[disabled]="errorSelector"
[(ngModel)]="ngxval_selector"
[items]="items"
</ngx-select>

Just remove the attribute disabled:

<ngx-select
[multiple]="true"
[(ngModel)]="ngxval_selector"
[items]="items"
</ngx-select>

And when you have items to show, launch (in component): this.selector.enable();

Solution 7 - Angular

Only who are using reactive forms : For native HTML elements [attr.disabled] will work but for material elements we need to dynamically disable the element.

this.form.get('controlname').disable();

Otherwise it will show in console warning message.

Solution 8 - Angular

This was my solution:

this.myForm = this._formBuilder.group({
    socDate: [[{ value: '', disabled: true }], Validators.required],
    ...
)}

<input fxFlex [matDatepicker]="picker" placeholder="Select Date" formControlName="socDate" [attr.disabled]="true" />

Solution 9 - Angular

I tried these in angular 7. It worked successfully.

this.form.controls['fromField'].reset();
if(condition){
      this.form.controls['fromField'].enable();
}
else{
      this.form.controls['fromField'].disable();
}

Solution 10 - Angular

When you create new Form control, use next:

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

If you want change activity, use next:

this.variable.enable() 

or

this.variable.disable()

Solution 11 - Angular

disabling of mat form fields is exempted if you are using form validation,so do make sure that your form field does not have any validations like(validators.required),this worked for me. for ex:

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

this makes the phone numbers of user to be non editable.

Solution 12 - Angular

@Input('disableControlDirective') disableControlDirective;
   ngOnChanges(values) {
    if (values['disableControlDirective']) {
      const disableOrEnable = this.disableControlDirective ? 'disable' : 'enable';
      this.ngControl.control[disableOrEnable]();
    }
  }

https://stackoverflow.com/a/60075989/14990860

Solution 13 - Angular

in Angular-9 if you want to disable/enable on button click here is a simple solution if you are using reactive forms.

define a function in component.ts file

//enable example you can use the same approach for disable with .disable()

toggleEnable() {
  this.yourFormName.controls.formFieldName.enable();
  console.log("Clicked")
} 

Call it from your component.html

e.g

<button type="button" data-toggle="form-control" class="bg-primary text-white btn- 
                reset" style="width:100%"(click)="toggleEnable()">

Solution 14 - Angular

Use [attr.disabled] instead [disabled], in my case it works ok

Solution 15 - Angular

add disable="true" to html field Example :disable

<amexio-text-input formControlName="LastName" disable="true" [(ngModel)]="emplpoyeeRegistration.lastName" [field-label]="'Last Name'" [place-holder]="'Please enter last name'" [allow-blank]="true" [error-msg]="'errorMsg'" [enable-popover]="true" [min-length]="2"
[min-error-msg]="'Minimum 2 char allowed'" [max-error-msg]="'Maximum 20 char allowed'" name="xyz" [max-length]="20">
[icon-feedback]="true">
</amexio-text-input>

Solution 16 - Angular

The beauty of reactive forms is you can catch values changes event of any input element very easily and at the same time you can change their values/ status. So here is the another way to tackle your problem by using enable disable.

Here is the complete solution on stackblitz.

Solution 17 - Angular

add name attribute to your md-input. if it doesn't solve the problem, please post your template

Solution 18 - Angular

It looks like you're using the disabled attribute with a reactive form directive. If you set disabled to true when you set up this control in your component class, the disabled attribute will actually be set in the DOM for you. We recommend using this approach to avoid 'changed after checked' errors.

Example:

form = new `FormGroup`({
    first: new FormControl({value: 'Nancy', disabled: true}, Validators.required),
    last: new FormControl('Drew', Validators.required)
});

Solution 19 - Angular

Ultimate way to do this.

ngOnInit() {
  this.interPretationForm.controls.InterpretationType.valueChanges.takeWhile(()=> this.alive).subscribe(val =>{
    console.log(val); // You check code. it will be executed every time value change.
  })
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFacundoGFloresView Question on Stackoverflow
Solution 1 - AngularbhantolView Answer on Stackoverflow
Solution 2 - AngularAnuj TBEView Answer on Stackoverflow
Solution 3 - AngularKaloyan StamatovView Answer on Stackoverflow
Solution 4 - AngularBBaysingerView Answer on Stackoverflow
Solution 5 - AngularExcellent CodingView Answer on Stackoverflow
Solution 6 - AngularIgnacio AraView Answer on Stackoverflow
Solution 7 - AngularTilak BhandariView Answer on Stackoverflow
Solution 8 - AngularFrank CoronaView Answer on Stackoverflow
Solution 9 - AngularRecep DumanView Answer on Stackoverflow
Solution 10 - AngularAleksandr ZelenskiyView Answer on Stackoverflow
Solution 11 - AngularSomesh TView Answer on Stackoverflow
Solution 12 - Angularuser14990860View Answer on Stackoverflow
Solution 13 - AngularSaad AbbasiView Answer on Stackoverflow
Solution 14 - AngularExari ConstantinView Answer on Stackoverflow
Solution 15 - AngularSagar JadhavView Answer on Stackoverflow
Solution 16 - AngularKedar9444View Answer on Stackoverflow
Solution 17 - AngularTaha ZguedView Answer on Stackoverflow
Solution 18 - AngularDeepakView Answer on Stackoverflow
Solution 19 - Angularuser3345544View Answer on Stackoverflow