Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs currency format in input box with ng-model: how to get $formatters to fire on each input

I have searched everywhere for this. Every stack overflow that has an answer, it does not actually work. Same with any examples or google group examples from for angular including the docs.

Seems simple. I want a function to get called on an input for each key pressed by the user.

simple input with a ng-model

<input class="form-control" ng-model="model.thisisnotfun" formatter type="text" required>

According to everything i read. $formatters should update the value from the model to the view calling any functions in the $formatters array. They never get called when i type in the input box.

.directive('formatter', function ($filter, $parse) {
    return {
        require: 'ngModel',

        link: function (scope, element, attrs, ngModel) {

            ngModel.$formatters.push(
                function (value) {
                    console.log('this only gets called on page load');
                }
            );
        }
    };
})

I know there are plenty of custom ways to do this, which i have already done. I do not need a work around, i just want to know how to use $formatters correctly to "format" the view data.

very very simple jsfiddle http://jsfiddle.net/fh7sB/4/

Thanks for any help.

like image 414
j_walker_dev Avatar asked Sep 22 '13 06:09

j_walker_dev


2 Answers

I could not get the $formatters function to work like i wanted. I also could not find a single example of what i was looking for anywhere so i am going to post my answer in case someone needs it.

This is a directive for formatting us currency in input boxes with ng-model

    .directive('uiCurrency', function ($filter, $parse) {
    return {
        require: 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs, ngModel) {

            function parse(viewValue, noRender) {
                if (!viewValue)
                    return viewValue;

                // strips all non digits leaving periods.
                var clean = viewValue.toString().replace(/[^0-9.]+/g, '').replace(/\.{2,}/, '.');

                // case for users entering multiple periods throughout the number
                var dotSplit = clean.split('.');
                if (dotSplit.length > 2) {
                    clean = dotSplit[0] + '.' + dotSplit[1].slice(0, 2);
                } else if (dotSplit.length == 2) {
                    clean = dotSplit[0] + '.' + dotSplit[1].slice(0, 2);
                }

                if (!noRender)
                    ngModel.$render();
                return clean;
            }

            ngModel.$parsers.unshift(parse);

            ngModel.$render = function() {
                console.log('viewValue', ngModel.$viewValue);
                console.log('modelValue', ngModel.$modelValue);
                var clean = parse(ngModel.$viewValue, true);
                if (!clean)
                    return;

                var currencyValue,
                    dotSplit = clean.split('.');

                // todo: refactor, this is ugly
                if (clean[clean.length-1] === '.') {
                     currencyValue = '$' + $filter('number')(parseFloat(clean)) + '.';

                } else if (clean.indexOf('.') != -1 && dotSplit[dotSplit.length - 1].length == 1) {
                    currencyValue = '$' + $filter('number')(parseFloat(clean), 1);
                } else if (clean.indexOf('.') != -1 && dotSplit[dotSplit.length - 1].length == 1) {
                    currencyValue = '$' + $filter('number')(parseFloat(clean), 2);
                } else {
                     currencyValue = '$' + $filter('number')(parseFloat(clean));
                }

                element.val(currencyValue);
            };

        }
    };
})
like image 147
j_walker_dev Avatar answered Oct 20 '22 02:10

j_walker_dev


The $formatters get called when the model is updated in order to format the value to be presented to the user. The $parsers do the opposite, i.e. translate the value from a view string to a real model, e.g. a number.

In the forked fiddle here: http://jsfiddle.net/9tuCz/ press the button; it changes the model and fires the $formatters again.

like image 24
Nikos Paraskevopoulos Avatar answered Oct 20 '22 02:10

Nikos Paraskevopoulos