Angular.js: ng-required="true" does not allow to empty field when using ng-model-options="{ getterSetter: true }"

Created on 18 Mar 2015  路  6Comments  路  Source: angular/angular.js

When using both ng-required="true" and ng-model-options="{ getterSetter: true }",
there is no possibility to empty the field. You always get the last character 'standing' in the input field.
This happens because 'newName' value in getter-setter function for name is undefined when value is empty. It happens only when using ng-required="true". If the field is not required, we get just empty string and everyrhing works fine.

Here is the code example:

<input type="text" name="userName"
           ng-required="true"
           ng-model="user.name"
           ng-model-options="{ getterSetter: true }" />
(function(angular) {
  'use strict';
angular.module('getterSetterExample', [])
  .controller('ExampleController', ['$scope', function($scope) {
    var _name = '';
    $scope.user = {
      name: function(newName) {
        console.log(newName);
        if (angular.isDefined(newName)) {
          _name = newName;
        }
        return _name;
      }
    };
  }]);
})(window.angular);
forms works as expected bug

Most helpful comment

Using allowInvalid will work around the issue, but it is not solving the actual problem.
The actual problem lies in the implementation of name(), which treats _passing an argument with value undefined_ as _passing no argument at all_ (although these are obviously two very distinct cases).

You should use a more "accurate" way of defining whether the function is called as a getter or as a setter (i.e. whether newName has been passed (even if undefined) or not).
E.g.:

name: function(newName) {
  if (arguments.length) {
    _name = newName || '';
  }
  return _name;
}

Demo

I think everything works as expected, so there's nothing actionable here.

All 6 comments

Can you please put the code as a runnable example on a plnkr.co or similar?

Hi Narretz,

here is the example: http://plnkr.co/edit/P5NaLBwWYB2v8O9U0W0A?p=preview

@mmazo You need to turn off validation by passing allowInvalid: true to your ng-model-options. You can see a working plnkr here: http://plnkr.co/edit/6vuK2vAb9m24eRL5uQ0Q?p=preview

You can see a more details from ngConf here: https://www.youtube.com/watch?v=k3t3ov6xHDw&t=211

Using allowInvalid will work around the issue, but it is not solving the actual problem.
The actual problem lies in the implementation of name(), which treats _passing an argument with value undefined_ as _passing no argument at all_ (although these are obviously two very distinct cases).

You should use a more "accurate" way of defining whether the function is called as a getter or as a setter (i.e. whether newName has been passed (even if undefined) or not).
E.g.:

name: function(newName) {
  if (arguments.length) {
    _name = newName || '';
  }
  return _name;
}

Demo

I think everything works as expected, so there's nothing actionable here.

Thanks @gkalpak, I agree, this is not a bug.

Thanks @gkalpak, the solution is really good. You are right, @Narretz, this is not a bug.

Was this page helpful?
0 / 5 - 0 ratings