4

I'm looking for a way to format an input element to format for currency. Specifically I want the commas in there for thousands.

The initial solution was to just format the value in the controller and return that to the view. But then to do my calculations I have to strip all of that out again. Then I came across $formatters and $parsers for ngModelController. Essentially it allows you to create pipeline functions. The first formats the value for the user. The second parses the value to be used in the controller. Precisely what I want.

My solution only works on page load though. Check out my fiddle.

myApp.directive('thousandsformatter', function ($filter) {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$formatters.push(function (data) {
                var formatted = $filter('currency')(data);
                console.log(formatted);
                //convert data from model format to view format
                return formatted; //converted
            });
            ctrl.$parsers.push(function (data) {
                console.log(data);
                //convert data from view format to model format
                return data; //converted
            });
        }
    };
});

How can I get this to update as the user types?

10
  • 1
    You may want to look at angular-ui. I think they have a directive for a input "mask". angular-ui.github.io/ui-utils Commented Nov 12, 2013 at 18:09
  • You want a filter, specifically the number one already does the commas and decimal place truncation so it's a good place to start. ah actually there's a currency one too docs.angularjs.org/api/ng.filter:currency Commented Nov 12, 2013 at 18:14
  • How do you use a filter on an input element? I know how to do it within scope bindings {{ }} Commented Nov 12, 2013 at 18:16
  • @TimWithers that looks like a good option. Is there a currency mask? Demo on their site doesn't show one. Commented Nov 12, 2013 at 18:22
  • 1
    Here is my best attempt jsfiddle.net/469MC/12. I feel like the idea in general is too invasive, I wouldn't want a field to keep updating (moving commas) as I type. I think it makes sense for masks, where the field size is fix, but I think just leaving it as an input type="number" and displaying the formatted result in a span nearby would be the best idea. Commented Nov 12, 2013 at 18:45

1 Answer 1

4

I've made an adjust in the parse function and now it's working like you want.

myApp.directive('thousandsformatter', function ($filter) {
    var precision = 2;
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$formatters.push(function (data) {
                var formatted = $filter('currency')(data);
                console.log(formatted);
                //convert data from model format to view format
                return formatted; //converted
            });
            ctrl.$parsers.push(function (data) {
                var plainNumber = data.replace(/[^\d|\-+|\+]/g, '');
                var length = plainNumber.length;
                var intValue = plainNumber.substring(0,length-precision);
                var decimalValue = plainNumber.substring(length-precision,length)
                var plainNumberWithDecimal = intValue + '.' + decimalValue;
                //convert data from view format to model format
                var formatted = $filter('currency')(plainNumberWithDecimal);
                element.val(formatted);

                return Number(plainNumberWithDecimal);
            });
        }
    };
});

Check out my solution on fiddle.

Hope it help.

Cheers

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.