40

Given a conditionally disabled text input field using ng-disabled="truthy_scope_variable", AngularJS disables the field the first time the scope variable is falsified, but does not enable it on subsequent changes. As a result, the field remains disabled. I can only assume something went wrong, but the Console log is empty.

The truthy scope variable is tied to a radio button model and I can even $watch it change, but the input field's ng-disabled is not working as expected. I have manually tried calling $apply, but it looks like Angular is triggering DOM changes.

In controller:

$scope.new_account = true

Radio buttons:

<input type="radio" ng-model="new_account" name="register"
 id="radio_new_account" value="true" />

<input type="radio" ng-model="new_account" name="register"
 id="radio_existing_account" value="false" />

Conditionally disabled input field:

<input type="password" ng-disabled="new_account" id="login-password"
 name="password" ng-model="password" />

If I initially set $scope.new_account = false, the field is rendered disabled, but never re-enabled. Why is this happening?

Tivie
  • 18,864
  • 5
  • 58
  • 77
Petrus Theron
  • 27,855
  • 36
  • 153
  • 287
  • Have you tried using just checkbox instead of radio button. It's neater. Look at this http://docs.angularjs.org/api/ng.directive:ngDisabled – dcodesmith Jul 25 '13 at 10:28

3 Answers3

32

That's because HTML attributes are always strings, so in your example ngDisabled is evaluating a string in both cases ("true" or "false").

To remedy, you should compare the model against the string value in ngDisabled:

ng-disabled="new_account == 'false'"

... or use a checkbox, to get the actual boolean value:

<input type="checkbox" ng-model="existing_account" name="register" id="checkbox_new_account" />
<label for="checkbox_new_account">Is Existing Account</label>

Password:
<input type="password" ng-disabled="existing_account" name="password" ng-model="password" />

Here's a PLNKR with both solutions.

Stewie
  • 60,366
  • 20
  • 146
  • 113
16

There is an alternative solution available just use

ng-value

 <input type="radio" ng-model="new_account" name="register"
 id="radio_new_account" ng-value="true" />

<input type="radio" ng-model="new_account" name="register"
 id="radio_existing_account" ng-value="false" />
      <input type="password" ng-disabled="new_account" id="login-password"
 name="password" ng-model="password" />
Ajay Beniwal
  • 18,857
  • 9
  • 81
  • 99
  • Your ng-value advice also fixes the problem! I wish I could mark both your answers as correct. – Petrus Theron Jul 25 '13 at 10:57
  • After working with AngularJS some more, `ng-value` seems the more idiomatic way. If you update your answer with why it works, I'll mark this as the accepted answer. – Petrus Theron Dec 05 '13 at 14:34
1

As of 2016 March the binded values will update the ui in Chrome and Firefox even when the ng-disabled is true but not in Safari. In Safari when you use ng-disabled the ui wont update although the input element value property will have the updated value (Check element.value after changing it.)

In Safari to force the ui updates with ng-model or ng-value directives you have to use ng-readonly instead of ng-disabled.

NoNameProvided
  • 8,608
  • 9
  • 40
  • 68