Reputation: 17878
I am trying to make an input that simulates type="number"
but I want to add my own buttons to it. Basically I've made
<form name="fasdf">
<button class="btn" ng-click="decrement()">◄</button>
<input type="text" ng-model="model" display-as-number />
<button class="btn" ng-click="increment()">►</button>
</form>
I'm using input type="text"
because I don't want the user agent to add it's own buttons to the field.
It should be possible to use the input
itself to enter a value as well as using the buttons to increment or decrement the value.
angular.module('app',[])
.controller('Ctrl', ['$scope', function($scope) {
$scope.model = 0;
$scope.decrement = function() {
$scope.model--;
};
$scope.increment = function() {
$scope.model++;
};
}])
The value is initially 0
but when the user starts entering text I want any leading zeros to be stripped as they type (well, actually the suits want that but you get my drift).
My theory was that I could use a $formatter
and/or a $parser
to do this by making a directive that accesses the ngModelController
.
angular.module('app')
.directive('displayAsNumber', [function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, controller) {
controller.$formatters.push(function (modelValue) {
var value = parseInt(modelValue, 10);
return value;
});
controller.$parsers.push(function (viewValue) {
var value = parseInt(viewValue, 10);
return value;
});
};
}]);
But while the $formatter
is being run every time I type something in the input, it is not overriding the actual value of the input field, in other words it is not stripping any leading zeros.
I can get this working by listening on DOM events (although I can't change the value on each keyup as that will move the cursor to the end of the field) by replacing the directive body with
element.on('focus', function() {
var value = parseInt(element.val(), 10);
if (value === 0)
element.val('');
});
element.on('focusout', function() {
if ('' === element.val().trim())
element.val(0);
else
element.val(parseInt(element.val(), 10));
});
The resulting behaviour is good enough (it blanks out the field on focus if the value is 0
and strips leading 0s
on focusout.
Question is, is there any way I could have achieved this behaviour without adding event-listeners to element
?
How do I properly control how the input is rendered using ngModelController
?
Plnkr: http://plnkr.co/edit/YOkFGNGamfA1Xb9pOP1U?p=preview
Upvotes: 2
Views: 2945
Reputation: 17878
So, yeah, after looking at other new questions I saw this and realized I was simply missing a call to controller.$render()
controller.$parsers.push(function (viewValue) {
var value = parseInt(viewValue, 10);
controller.$viewValue = value;
controller.$render();
return value;
});
Fixes my problem. I'll go away now.
Upvotes: 3