Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS Directive Numeric Format Masking

The directive I have created uses the function setFormatting to mask the text value in an input field.

scope.$watch(element, function() {
    modelCtrl.$setViewValue(setFormatting(element.val(), attrs.symbol));
    modelCtrl.$render();
});

element.bind('blur', function() {
    modelCtrl.$setViewValue(setFormatting(element.val(), attrs.symbol));
    modelCtrl.$render();
});

The scope.$watch applies the mask when the content is loaded/applied the first time, the element.bind applies the mask for the other times. The scope.$watch is storing the symbol (if there is one) as part of the ng-model variable. The element.bind is not. I thought $setViewValue() and $render() did not update the ng-model variable. Where is the variable being updated?

See attached fiddle: http://jsfiddle.net/PJ3M4/
Thanks.

like image 719
C1pher Avatar asked Jan 21 '26 03:01

C1pher


2 Answers

Here we used $formatters.unshift and $filter:

enter image description here

JS

var fessmodule = angular.module('myModule', []);

fessmodule.controller('fessCntrl', function ($scope) {
    $scope.test = 123456879;
});
fessmodule.$inject = ['$scope'];

fessmodule.directive('format', ['$filter', function ($filter) {
    return {
        require: '?ngModel',
        link: function (scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            var symbol = "°"; // dummy usage

            ctrl.$formatters.unshift(function (a) {
                return $filter(attrs.format)(ctrl.$modelValue) +  symbol;
            });

            ctrl.$parsers.unshift(function (viewValue) {
                var plainNumber = viewValue.replace(/[^\d|\-+|\.+]/g, '');
                elem.val($filter('number')(plainNumber) + symbol);
                return plainNumber;
            });
        }
    };
}]);

HTML

 <input type="text" ng-model="test" format="number"/>

Demo Fiddle

As a side note

You can find this helpful too: Fiddle

like image 107
Maxim Shoustin Avatar answered Jan 24 '26 06:01

Maxim Shoustin


The $watch is executed inside a 'digest' loop. The element.bind callback is called from outside angular, so you must add an explicit call to scope.$apply():

element.bind('blur', function() {
    modelCtrl.$setViewValue(setFormatting(element.val(), attrs.symbol));
    modelCtrl.$render();
    scope.$apply();
});

Updated fiddle

See the docs for info about AngularJS's event loop.

like image 27
rvignacio Avatar answered Jan 24 '26 08:01

rvignacio



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!