28

Up until "final" 2.0 of Angular I have done this:

<input type="text" formControlName="name" [disabled]="!showName">

To dynamically disable/enable form inputs.

After upgrading from Rc7 to 2.0 I get this warning in the console window:

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.

I have changed my code to follow these instructions like this:

this._userGroupUsersForm = this._formBuilder.group({
        'users': [{'', disabled: this.showName}, Validators.compose([Validators.required, Validators.minLength(3), Validators.maxLength(50), Validators.pattern("^[a-zA-ZåäöÅÄÖ 0-9_-]+$")])]
    });

And that works fine for the initial page load, but I can no longer toggle the status like this:

toggleName() : void { this.showName = !this.showName; }

How do I solve this?

Note: My "old" way of doing this (by setting [disabled]) doesn't work any more either.

Glenn Utter
  • 2,313
  • 7
  • 32
  • 44

6 Answers6

29

This same issue had me pulling my hair. My solution was to use interpolation rather than one-way binding to update the property. In your case, instead of using:

<input type="text" formControlName="name" [disabled]="!showName">

you could do:

<input type="text" formControlName="name" disabled="{{!showName}}">

As soon as I did that, I was able to dynamically disable / enable elements in my forms.

I hope this helps!

Vidal Quevedo
  • 986
  • 10
  • 10
  • This doesn't compile in Anglar 4: `Parser Error: Got interpolation ({{}}) where expression was expected` – FelixM Nov 19 '17 at 20:39
  • It sounds like you may be doing [disabled]="{{interpolation}}". Mind providing a sample of your code? Thanks! – Vidal Quevedo Nov 20 '17 at 15:16
20

This should work

toggleName() : void { 
  let ctrl = this.form.get('name')
  ctrl.enabled ? ctrl.disable() : ctrl.enable()
}
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    It does! You are awesome sir. Thank you! It does however still complain on the submit button that looks like this ` – Glenn Utter Sep 15 '16 at 07:44
  • Complain about what. Can you please post the exact error? – Günter Zöchbauer Sep 15 '16 at 07:49
  • Sorry about that. It's the exact same error message as before. I guess it looks at all [disabled] and shows it? – Glenn Utter Sep 15 '16 at 07:55
  • I see. I think this is a bug then. There is no control for the button. Would you mind report it in http://github.com/angular/angular ? – Günter Zöchbauer Sep 15 '16 at 07:57
  • 1
    It's not a bug. It was a child component containing [disabled]. Thank you! – Glenn Utter Sep 15 '16 at 08:01
  • What will we do if there are 20 controls and want to disable all at a time? – sainu Feb 07 '17 at 06:42
  • @sainu ... you would have to get a reference to all 20 controls and change their disabled property using the corresponding method, which is a more code than just plain changing the disabled prop in the template like in the answer below. – Boban Stojanovski Apr 27 '17 at 10:25
  • Hard to tell. It depends on how your code looks like. I'd suggest to create a new question. You can use `this.form.controls` to get all controls (at one level) and call `ctrl.disabled()` for each one. – Günter Zöchbauer Apr 27 '17 at 10:30
20

You can try to use readonly attribute in your input.

disabled >>> readonly

<input type="text" formControlName="name" [readonly]="!showName">
barış çıracı
  • 1,033
  • 14
  • 16
7

As of RC6 you need to call the disable() function RC6 Forms: disabled attribute cannot be set dynamically anymore.

JayChase
  • 11,174
  • 2
  • 43
  • 52
4

If somebody scrolls through this and the accepted answer (Günters) doesn't work, as it didn't for me at first. It might be that you are trying to use it with a custom component and haven't implemented the optional method setDisabledState(isDisabled: boolean) from the ControlValueAccessor interface.

Hampus
  • 2,769
  • 1
  • 22
  • 38
  • 1
    using a custom component (for different types of fields) propagating changes (extends ControlValueAccessor). Tried interpolation as in previous comment, but your solution was in my case what worked, seems practical, just updated how form control is created (explicit constructor with disabled attribute) and added the setdisabledStatus method which sets the internal disabled property of my custom component. thanks. – kandan Dec 28 '17 at 13:10
1

You must be using:

[attr.disabled]

Instead of:

[disabled]

I hope it works.

Koby Douek
  • 16,156
  • 19
  • 74
  • 103
dodinh anh
  • 11
  • 1