Reputation: 1171
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!!
Upvotes: 0
Views: 1018
Reputation: 3664
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.
Upvotes: 1
Reputation: 7179
Other than creating a filter you can also calculate on the template
<span>{{percentValue * 100}}</span>
Upvotes: 0
Reputation: 5064
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.
Upvotes: 0
Reputation: 498
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>
Upvotes: 0