I would like to create directive for writing only numbers with decimal places. I have this code:
zpc. directive('onlyNumbers', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
if (inputValue == undefined) return '';
var transformedInput = inputValue.replace(/^[0-9](,[0-9]{0,2})?/g, '');
if (transformedInput !== inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
I can write numbers with decimal places but other characters too.
Thanks for advices
angular.directive('decimalPlaces',function(){
return {
link:function(scope,ele,attrs){
ele.bind('keypress',function(e){
var newVal=$(this).val()+(e.charCode!==0?String.fromCharCode(e.charCode):'');
if($(this).val().search(/(.*)\.[0-9][0-9]/)===0 && newVal.length>$(this).val().length){
e.preventDefault();
}
});
}
};
});
<input type="number" step="0.01" ng-model='somemodel' decimal-places>
You can also used https://www.npmjs.com/package/angular-input-masks.
Hopefully this will help.
use ng-pattern directive, set regular expression.
<input type="text" ng-model="onlyNumbers" ng-pattern="/^[0-9]+\.?[0-9]*$/">
Related
I have a directive to check if input value is number or not and according to perform action
myApp.directive('numbersOnly', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function fromUser(text) {
if (text) {
var transformedInput = text.replace(/[^0-9-]/g, '');
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(fromUser);
}
};
});
this above code will work when i will use <input type="text"/> but when i will use <input type="number"/> the above code will stop the work.
Please tell me how to support both ?
Can you try the below code which has one more condition(isNaN) in 'if' as below,
myApp.directive('numbersOnly', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function fromUser(text) {
if (text && isNaN(text)) {
var transformedInput = text.replace(/[^0-9-]/g, '');
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(fromUser);
}
};
});
Below code fixed my issue
myapp.directive('numbersOnly', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function fromUser(value) {
if (value) {
if(!isNaN(value)){
var text = value.toString();
}
else{
var text = value;
}
var transformedInput = text.replace(/[^0-9-]/g, '');
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(fromUser);
}
};
});
So this code will work for both the cases
<input type="text"/> or <input /> and as well as <input type="number"/>
Is there a way to not bind value to model , and ONLY bind it to model when value is valid.
Use $parsers. The example below restricts input to your model for numbers only. Obviously you can change that to be whatever you require to make your input valid.
angular.module('app').
directive('onlyDigits', function () {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
if (inputValue == undefined) return '';
var transformedInput = inputValue.replace(/[^0-9]/g, '');
if (transformedInput !== inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
<input type="text" name="number" only-digits>
Code sample comes from this SO question
I do not want a user to enter spaces in a text field. I don't want it on submit validation but rather - a space will not show up on the text field when they click it.
The selected answer is arguably not very unobtrusive. And if you need to use it in multiple places, you'll end up with duplicated code.
I prefer to prevent the input of spaces using the following directive.
app.directive('disallowSpaces', function() {
return {
restrict: 'A',
link: function($scope, $element) {
$element.bind('input', function() {
$(this).val($(this).val().replace(/ /g, ''));
});
}
};
});
This directive can be invoked like this:
<input type="text" disallow-spaces>
<input ng-model="field" ng-trim="false" ng-change="field = field.split(' ').join('')" type="text">
Update:
To improve code quality you can create custom directive instead. But don't forget that your directive should prevent input not only from keyboard, but also from pasting.
<input type="text" ng-trim="false" ng-model="myValue" restrict-field="myValue">
Here is important to add ng-trim="false" attribute to disable trimming of an input.
angular
.module('app')
.directive('restrictField', function () {
return {
restrict: 'AE',
scope: {
restrictField: '='
},
link: function (scope) {
// this will match spaces, tabs, line feeds etc
// you can change this regex as you want
var regex = /\s/g;
scope.$watch('restrictField', function (newValue, oldValue) {
if (newValue != oldValue && regex.test(newValue)) {
scope.restrictField = newValue.replace(regex, '');
}
});
}
};
});
If you want to achieve it without writing directive
ng-keydown="$event.keyCode != 32 ? $event:$event.preventDefault()"
THe directive Jason wrote did not work for me. I had to change return false to: e.preventDefault() like so:
app.directive('disallowSpaces', function() {
return {
restrict: 'A',
link: function($scope, $element) {
$element.bind('keydown', function(e) {
if (e.which === 32) {
e.preventDefault();
}
});
}
}
});
This works to prevent entering any special chars including spaces:
app.directive('noSpecialChar', function() {
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function(inputValue) {
if (inputValue == null)
return ''
let cleanInputValue = inputValue.replace(/[^\w]|_/gi, '');
if (cleanInputValue != inputValue) {
modelCtrl.$setViewValue(cleanInputValue);
modelCtrl.$render();
}
return cleanInputValue;
});
}
}
});
Use without jquery
angular.module('app').directive('disallowSpaces', function () {
return {
restrict: 'A',
require: 'ngModel',
scope: {
maxvalue: '=',
},
link: function ($scope, $element, attr, ngModelCtrl) {
$element.bind('keydown', function () {
function transformer(text) {
if (text) {
var transformedInput = text.replace(/ /g, '');
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(transformer);
});
},
};
});
// use disallow-spaces
<input type="text" ng-model="name" disallow-spaces />
You can achieve this without writing a directive.
<input ng-model="myModel" ng-keydown="$event.keyCode != 32 ? $event:$event.preventDefault()">
For Angular 9 ,Keycode is not support.
Below code can help you for that.
keyDownHandler(event) {
if (event.code === 'Space') {
event.preventDefault();
}
}
I am following an example based on official docs to validate float. My added requirement is that float value should lie between -90 to 90. I added the min and max fields but still no luck.
Below is the code:
HTML:
<body ng-app="form-example1">
<form name="form" class="css-form" novalidate>
<div>
Length (float):
<input type="text" ng-model="length" name="length" min="-90" max="90" smart-float />
{{length}}<br />
<span ng-show="form.length.$error.float">
This is not a valid float number!</span>
<span ng-show="form.length.$error.min || form.length.$error.max">
The value must be in range -90 to 90!</span>
</div>
JS:
var app = angular.module('form-example1', []);
var FLOAT_REGEXP = /^\-?\d+((\.|\,)\d+)?$/;
app.directive('smartFloat', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (FLOAT_REGEXP.test(viewValue)) {
ctrl.$setValidity('float', true);
return parseFloat(viewValue.replace(',', '.'));
} else {
ctrl.$setValidity('float', false);
return undefined;
}
});
}
};
});
Right now validations for min and max fields are not working. 90 is allowed but anything higher than is not allowed (like 90.12345 is not allowed, 90 is allowed, 89.9999 is allowed, -90.1 is not allowed)
Be sure to make your input of type number! The min/max validation is only available for this type of input field. Compare the docs for number to text.
<input type="text" name="number" smart-float>
app.directive('smartFloat', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function(inputValue) {
if (inputValue == undefined) return '';
var transformedInput = inputValue.replace(/[^0-9.]/g, '');
if (transformedInput !== inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
European countries uses a comma-sign (,) instead of a dot (.) when they enter decimal numbers. So I want to replace the dot sign with a comma when users enter input. I'm aware that input=number do this but I need support for IE.
I guess directive is the best to do this? I gave it a try with the code below. But it fails.
.directive('replaceComma', function(){
return {
restrict: 'A',
replace: true,
link: function(scope, element, attrs){
scope.$watch(attrs.ngModel, function (v) {
var convert = String(v).replace(",",".");
attrs.NgModel = convert;
});
}
}
});
The convert variable is correct. But the value does not change in the input box. So I guess attrs.ngModel = convert, is wrong?
I think there is no need to do this like a directive.
say your template is
<input ng-model='someModel'>
in your controller,
$scope.$watch('someModel',function(newVal){
$scope.someModel = newVal.replace(/,/g,'.');
})
ng-model is a two-way binding, so it should work
Via directive:
.directive('replacecomma', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
scope.$watch(attrs.ngModel, function (newVal) {
if (newVal !== undefined && newVal !== null) {
ngModelCtrl.$setViewValue(String(newVal).replace(/,/g, '.'));
element.val(String(newVal).replace(/,/g, '.'));
}
})
}
}
});
var mystring = "this,is,a,test"
mystring = mystring.split(',').join(' ');
mystring contain ==> "this is a test"
In your template:
<input type="text" ng-model="someModel" replace-comma >
in your module :
.directive('replaceComma', function(){
return {
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function fromUser(text) {
if (text) {
var transformedInput = text.replace(/,/g, '.')
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(fromUser);
}
};});