0

I have a view tht has the following requirements:

  • HTML input type must be number
  • Programatically set the value of the model attribute of that input with 2 trailing decimals
  • Allow for user input to modify that value

Now, seting the value programatically as 1.20 for that value to display in the input is complicated:

  • parseFloat(1.20) returns 1.2
  • (1.20).toFixed(2) returns a string '1.20', for which AngularJS fails when attempting to set the value

Any ideas?

MonOve
  • 1,091
  • 13
  • 34
  • Use the [`ng-pattern` directive](https://docs.angularjs.org/api/ng/directive/ngPattern) or create a [custom directive](https://docs.angularjs.org/guide/directive) that uses the [ngModelController API](https://docs.angularjs.org/api/ng/type/ngModel.NgModelController) – georgeawg Jun 18 '18 at 21:23

2 Answers2

1

Based on https://github.com/angular/angular.js/issues/5680#issuecomment-206325921 I did the following:

(function(){
    angular.module('app')
        .directive('toFixed', [function () {
            return {
                require: '^ngModel',
                link: function(scope, element, attrs, ngModel) {
                    ngModel.$formatters.push(function(value) {
                        return parseFloat(value);
                    });
                    ngModel.$render = function() {
                        var viewValue = parseFloat(ngModel.$viewValue || 0);
                        element.val(viewValue.toFixed(2));
                    }
                }
            };
        }]);
}());
MonOve
  • 1,091
  • 13
  • 34
0

You can take advantage of NgModel and add a parser or formatter.

function NumberFormatter($filter){
'ngInject';

return {
    restrict: 'A',
    require: '^ngModel',
    link: function(scope, element, attrs, ngModelCtrl){
          //format text going to user (model to view)
          ngModelCtrl.$formatters.push(function(value) {
             return $filter('number')(parseFloat(value) , 2);
          });

          //format text from the user (view to model)
          ngModelCtrl.$parsers.push(function(value) {
            return doParsing(value)
          });
    }
}
}

ngModel Formatters and Parsers

Phil Ninan
  • 1,108
  • 1
  • 14
  • 23
  • 1
    When creating custom directives that work with the `ng-model` directive it is best to avoid using isolate scope. Also avoid two-way binding with the `ng-model` attribute; use one-way binding (`<`) for input, `$setViewValue` for output. – georgeawg Jun 18 '18 at 22:48
  • looks like i can remove the isolate scope in this case. – Phil Ninan Jun 19 '18 at 14:27
  • This solution doesn't address the main issue that formatting the value with `toFixed` fails when rendering to the view, as input type is number, not string (which `toFixed` returns), otherwise I get `Error: [ngModel:numfmt] Expected 1.20 to be a number` – MonOve Jun 19 '18 at 16:59
  • Could you use a number input step instead of toFixed()? https://stackoverflow.com/questions/22641074/html5-number-input-always-show-2-decimal-places – Phil Ninan Jun 19 '18 at 17:09
  • I updated the answer to include a number filter which should always display two decimal places. – Phil Ninan Jun 19 '18 at 17:17
  • Unfortunately it doesn't work. Same old error. `typeof $filter('number')(parseFloat(value) , 2)` = `'string'` – MonOve Jun 19 '18 at 17:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/173417/discussion-between-monove-and-phil-ninan). – MonOve Jun 19 '18 at 17:24