Search code examples
angularjsfilterformatcurrencyangular-directive

Angular filter for currency to allow typing negative numbers


I have a directive that filters currency by adding a decimal point as the user types.

My problem is that it will not allow negatives. It would be nice to allow a user to type a '-' sign and have it always appear at the beginning of the number, or type a '+' and have it disappear.

Needs:

  1. Format decimal field as user types
  2. Field must be a number
  3. Must allow negatives -
  4. Allow 0.00 as a number input

Check out my Plunker here . It has input = number but does not allow negative numbers:

app.directive('format', ['$filter', function ($filter) {
    return {
        require: 'ngModel', //there must be ng-model in the html
        link: function (scope, elem, attr, ctrl) {
            if (!ctrl) return;

            ctrl.$parsers.unshift(function (viewValue, modelValue) {
                var plainNumber = viewValue.replace(/[^-+0-9]/g,'');

                // use angular internal 'number' filter
                plainNumber = $filter('number')(plainNumber / 100, 2).replace(/,/g, '');

                // update the $viewValue
                ctrl.$setViewValue(plainNumber);

                // reflect on the DOM element
                ctrl.$render();

                // return the modified value to next parser
                return plainNumber;
            });
        }
    };
}]);

Solution

  • This will do exactly what you want it to do:

    var app = angular.module('App',[]);
    
     app.controller('MainCtrl', function ($scope) {
    
    
    });
    
     app.directive('format', ['$filter', function ($filter) {
     return {
                require: 'ngModel', //there must be ng-model in the html
                link: function (scope, elem, attr, ctrl) {
                    if (!ctrl) return;
    
                    ctrl.$parsers.unshift(function (viewValue, modelValue) {
                        var plainNumber = viewValue.replace(/[^-+0-9]/g,'');
                        var newVal = plainNumber.charAt(plainNumber.length-1);
                        var positive = plainNumber.charAt(0) != '-';
                        if(isNaN(plainNumber.charAt(plainNumber.length-1))){
                          plainNumber = plainNumber.substr(0,plainNumber.length-1)
                        }
                        //use angular internal 'number' filter
                        plainNumber = $filter('number')(plainNumber / 100, 2).replace(/,/g, '');
                        if(positive && newVal == '-'){
                          plainNumber = '-' + plainNumber;
                        }
                        else if(!positive && newVal == '+'){
                          plainNumber = plainNumber.substr(1);
                        }
                        plainNumber.replace('.', ',');
                        //update the $viewValue
                        ctrl.$setViewValue(plainNumber);
                        //reflect on the DOM element
                        ctrl.$render();
                        //return the modified value to next parser
                        return plainNumber;
                    });
                }
            };
    
    }]);
    

    Just remove the type="number" from:

    <input ng-model="amount" format="number" />