Search code examples
javascriptangularjsecmascript-5

$parsers and $formatters are being called only once, instead of on every value update


I'm trying to create a directive named currency that appends a $ before the text in input. The dollar sign should be shown at all times and shouldn't be possible to remove.

Here's my code:

app.directive('currency', function() {
    return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, elem, attrs, controller) {

      // view -> model
      controller.$parsers.push(function (viewValue) {
        viewValue = viewValue.replace(/^\$/, '');
        controller.$viewValue = viewValue;
        return viewValue;
      });

      // model -> view
      controller.$formatters.push(function (modelValue) {
        modelValue = '$' + modelValue;
        controller.$modelValue = modelValue;
        return modelValue;
      });
    }
  };
});

Working example: https://jsfiddle.net/U3pVM/29012/

As you can see, the dollar sign is appended initially, but can be deleted and won't be appended after that. It seems that the function I push to $formatters is only being called once. Is it supposed to work like that or am I missing something? How can I implement the desired behavior?


Solution

  • ok, i have tried a workaround, it works but i am not sure if this is the correct way to do it.

    updated fiddle : https://jsfiddle.net/U3pVM/29014/

    controller.$parsers.push(function (viewValue) {
          //console.log(viewValue.substring(0,1));
    
          if(viewValue.substring(0,1) != "$"){
                var view_value = "$" + viewValue;
              controller.$setViewValue(view_value);
              controller.$render();
          }
            viewValue = viewValue.replace(/^\$/, '');
            //controller.$viewValue = viewValue;
    
    
            console.log(viewValue);
            return viewValue;
          });
    

    P.S: i am not sure why you are injecting ngModel as controller in your link function. it might be a mistake.