Adam
Adam

Reputation: 129

Angular Directive: ngModelController custom parser not called

I know that I can use formatters and parsers in my directive to transform my data like this:

  //format text going to user (model to view)
  ngModel.$formatters.push(function(value) {
    return value.toUpperCase();
  });

  //format text from the user (view to model)
  ngModel.$parsers.push(function(value) {
    return value.toLowerCase();
  });

Full example here http://plnkr.co/edit/i59xSdVPMxRkgERhj8RE?p=preview

But I can't get this to work when I am using a template inside my directive. My custom parser isn't called:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.data = { name: ''};
});
app.directive('changecase', function () {
  return {
    restrict: 'E',
    require: 'ngModel',
    scope: { model: '=ngModel' },
    template: '<input type="text" ng-model="model"> {{ model }}',
    link: function (scope, element, attrs, ctrl) {

      //format text going to user (model to view)
      ctrl.$formatters.push(function(value) {
        return value.toUpperCase();
      });

      //format text from the user (view to model)
      ctrl.$parsers.push(function(value) {
        return value.toLowerCase();
      });
    }
  }
});

With this html:

  <body ng-controller="MainCtrl">
    <changecase ng-model="data.name"></changecase>
    <pre>model is: {{data.name}}</pre>
  </body>

I'm guessing that this is either a scope or timing issue, but I can't work it out. Can anyone see what I'm doing wrong?

Feel free to mess around with the Plunker here: http://plnkr.co/edit/FZ4UnW8wIhIwRV2jVvfB?p=preview

Upvotes: 1

Views: 1079

Answers (1)

Petr Averyanov
Petr Averyanov

Reputation: 9476

The problem you have is quite simple - in your example you have 2 ng-models, one is in the changecase, another in input. You add formatter to the first, but u need second. So your directive should be just:

app.directive('changecase', function () {
  return {
    restrict: 'E',
    scope: { model: '=model' },
    template: '<input realuppercase type="text" ng-model="model"> {{ model }}',
    link: function (scope, element, attrs) {
    }
  }
});

Just template, so you probably want to remove it. (I changed ng-model to model, cause here is simply no need in ngModel directive) And new realuppercase:

app.directive('realuppercase', function () {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ctrl) {
      ctrl.$formatters.push(function(value) {
        return value.toUpperCase();
      });

      ctrl.$parsers.push(function(value) {
        return value.toLowerCase();
      });
    }
  }
});

Here is your modified plunk: http://plnkr.co/edit/UoSFFuCVnbAwerQYHc3o?p=preview (Type in caps -> model in lower case)

Upvotes: 2

Related Questions