0

So I have a decimal value in controller like this:

// Controller
var MyController = function($scope) {
    ...
    $scope.percentValue = 0.05; // can be stored
    ...
};

<!-- View -->
<span>{{percentValue}}</span>
<input ng-model="percentValue" />

With the above code, the value in the input element is 0.05 - however, I want to allow a user to enter an integer value like 5.

So if the $scope.percentValue is 0.05, I want to show it as 5 in the input element. And if a user enters 5, the $scope.percentValue should be 0.05.

However, the tricky thing here is I only want to update the view value - meaning that the span element should still show 0.05. Only the value in the input element should be 5.

I am trying to achieve this with ngModel, but I am still struggling.

This is what I have now:

var MyDirective = function() {
    function link(scope, element, attrs, ngModel) {
        ngModel.$render = function() {
            element.val(ngModel.$viewValue || '');
        };

        ngModel.$formatters.push(function (value) {
            return value * 100;
        });

        element.on('change blur', function() {
            ngModel.$setViewValue(element.val());
        }); 
    }

    return {
        restrict: 'A',
        require: '?ngModel',
        scope: {},
        link: link
    };
};

Please advise!!

6
  • try a filter instead. Commented Jun 14, 2017 at 23:50
  • 1
    @KimchiMan, you're already using $formatters to transform the model representation for display, so just simply define a $parsers to do it the other way, like so—plnkr.co/edit/lB6GaT1ZSrVsOi9PS1u9?p=preview Commented Jun 15, 2017 at 0:33
  • @miqid, your answer is exactly what I want - could you add the code in the answer section? I will mark it as the answer Commented Jun 15, 2017 at 14:15
  • @miqid also, I wonder if there is a way to achieve this without using value / 100 Commented Jun 15, 2017 at 14:54
  • 1
    @KimchiMan, are there any restrictions on what a user is expected, or allowed, to enter in that input? Any other context for what you're building might also help. If $formatters is already doing value * 100, I don't see why value / 100 doesn't make sense. Commented Jun 15, 2017 at 15:03

4 Answers 4

1

Including my comment as an answer because it seemed to help. :-)

To summarise: since you've already provided a $formatters function for your directive, which converts a model value ($modelValue) to displayed form ($viewValue), it's simply a matter of providing a $parsers function to do the reverse and convert any user input back to the model value.

Example Plunker

Sign up to request clarification or add additional context in comments.

Comments

0

What you're trying to achieve is probably possible, but I would find it really confusing to read the code. The simplest solution that I think would solve your problem and maintain readability is to store an integer value (5) in $scope.percentValue, so that ng-model is always dealing with an integer when typing and displaying the value in the <input>. Then create a custom filter and use it to output the value as 0.05 in the <span>.

Edit: adding a concrete code example. Play with it here: https://plnkr.co/edit/C1cX2L9B2GM2yax1rw7Z?p=preview

JS:

var MyController = function ($scope) {
  $scope.percentValue = 5;
};

function formatPercent (input) {
  return input / 100;
}

var myApp = angular.module('MyApp', []);
myApp.filter('percent', function () { return formatPercent });
myApp.controller('MyController', ['$scope', MyController]);

HTML:

<body ng-controller="MyController">
  <span>{{ percentValue | percent }}</span>
  <input ng-model="percentValue">
</body>

Comments

0

I'd create a filter for percentage :

angular.module('myModule')
.filter('percentage', ['$filter', function($filter) {
    return function(input, decimals) {
        return $filter('number')(input*100, decimals)+'%';
    };
}]);

The input will store integer (such as 5)

<input ng-model="percentValue" />

But I'll add a filter to the span part :

<span>{{percentValue | percentage:2}}</span>

Credit to https://stackoverflow.com/a/21727765/3687474 for the filter directive.

Comments

0

Other than creating a filter you can also calculate on the template

<span>{{percentValue * 100}}</span>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.