AngularJS Parsers and Formatters

Home / AngularJS Parsers and Formatters

angular_small
While Anuglar 4.x is all the rage, I continue to also work in Angular 1.x (AngularJS) projects. Earlier this week, a colleague of mine wanted to use an input mask that doesn’t affect an underlying ng-model value. We already had a directive using jquery.input-mask, but that modifies the model value. Formatters and parsers are suited well for this task of separating the view value and model value.


Parsers in AngularJS allow modifying the view value of an underlying bound model value. Formatters allowing intercept the view value input, like that which you would get from a user typing into a textbox, and format the underlying bound model value. Using a an ngModel controller, the parsers and formatters desired are simply defined and pushed on the $parsers and $formatters collections.

It’s pretty straight-forward to wrap this into a directive. As an example, below is a directive that will put dashes every (4) characters of the user input (ngModel.$viewValue), and, conversely, any dashes and whitespace are stripped from the bound model value (ngModel.$modelValue). This allows formatting even the HTML input’s display without resorting to too much trickery.

var maskedInput = function() {
  var directive = {
    restrict: 'EA',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      console.log("In link function");

      var addSpaces = function(value) {
        if (typeof(value) == typeof(undefined))
          return value;
        var parsedValue = value.toString()
          .replace(/[^\dA-Za-z]/g, '')
          .replace(/(.{4})/g, '$1-').trim()
          .toUpperCase()
          .replace(/-$/, '');
        return parsedValue;
      }

      var removeSpaces = function(value) {
        if (typeof(value) == typeof(undefined))
          return value;
        var parsedValue = value.toString().replace(/\s/g, '').replace(/-/g, '');
        return parsedValue;
      }

      var parseViewValue = function(value) {
        var viewValue = addSpaces(value);
        ngModel.$viewValue = viewValue;
        ngModel.$render();

        // Return what we want the model value to be
        return removeSpaces(viewValue);
      }

      var formatModelValue = function(value) {
        var modelValue = removeSpaces(value);
        ngModel.$modelValue = modelValue;
        return addSpaces(modelValue);
      }

      ngModel.$parsers.push(parseViewValue);
      ngModel.$formatters.push(formatModelValue);
    }
  };
  return directive;
}

The directive can be added to any input an as attribute. On a side-note, ng-model-options can be used to debounce the masking in order to maintain decent performance.

<input type="text" ng-model="vm.someInput" ng-model-options="{'debounce': 250 }" masked-input style="width: 100%; font-size: 1.3em" />

A plunker demo is below.

One thought on “AngularJS Parsers and Formatters”

Leave a Reply