HFA HFA - 3 months ago 28
AngularJS Question

Extending input by using my own service

I want to extend input of type text in angular in such a way that after user enters some text, the text value is passed through a custom filter that do some purification on entering input, here is what I have come until now, but I am getting an error:

angular.js:13920 TypeError: Cannot read property 'length' of undefined
at addDirective (http://bank.com:4000/vendor/bower_components/angular/angular.js:9495:35)
at collectDirectives (http://bank.com:4000/vendor/bower_components/angular/angular.js:8677:11)
at compileNodes (http://bank.com:4000/vendor/bower_components/angular/angular.js:8539:22)


here is what I have written:

angular.module('app').config(extendInputDirective);

function extendInputDirective($provide) {
$provide.decorator('inputDirective', function($delegate, $filter) {
debugger;
var directive = $delegate[0];

var link = directive.link;

directive.compile = function() {
return function(scope,element, attrs, ngModel) {
debugger;
if(attrs.type === 'text') {
ngModel.$parsers.unshift(function(viewValue) {
var value = $filter('pArabicCharFilter')(viewValue);
return value;
});
}
link.apply(this, arguments);
}
}
});

Answer

I am not sure if you want to update the model value or both the view and model value. I have assumed it is both.

To review the formatter and perser functionality:

  • Parsers are called as soon as the input is modified by the user. They format the text from the user. That is, a view to model update.

  • Formatters are invoked when the model is modified in the code. They are not invoked if the user modifies the input field. They format the text going to the user. That is, a model to view change.

Since formatters don't run when the ui is updated. You would need to update the view value manually as in the below example in which the input is automatically capitalized.

(function() {
  'use strict';
  angular
    .module('exampleApp', [])
    .directive('capitalize', CapitalizeDirective);

  function CapitalizeDirective($filter) {
    return {
      require: 'ngModel',
      link: function(scope, element, attrs, ngModelCtrl) {
        function capitalize(text) {
          var capitalizedText = $filter('uppercase')(text);
          ngModelCtrl.$setViewValue(capitalizedText);
          ngModelCtrl.$render();
          return capitalizedText;
        }
        ngModelCtrl.$parsers.push(capitalize);
      }
    };
  }
  CapitalizeDirective.$inject = ['$filter']; 
})();
<!DOCTYPE html>
<html ng-app='exampleApp'>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"></script>

</head>

<body>
  <label>
    First name:
    <input type="text" name="firstName" ng-model="firstName" capitalize>
  </label>
</body>

</html>

Comments