我在AngularJS中使用ngChange触发一个自定义函数,该函数将删除用户添加到输入中的任何字母。
<input type="text" name="inputName" data-ng-change="numbersOnly()"/>
问题是我需要定位触发numbersOnly()
的输入,以便我可以删除输入的字母。我在Google上看了很长时间,并且无法找到任何相关内容。
我该怎么办?
答案 0 :(得分:95)
简单方法,如果适用于您的用例,请使用type="number":
<input type="number" ng-model="myText" name="inputName">
另一种简单方法: ng-pattern也可用于定义将限制字段中允许的内容的正则表达式。另请参阅"cookbook" page about forms。
<强>的hackish?方式,$在你的控制器中观察ng-model:
<input type="text" ng-model="myText" name="inputName">
控制器:
$scope.$watch('myText', function() {
// put numbersOnly() logic here, e.g.:
if ($scope.myText ... regex to look for ... ) {
// strip out the non-numbers
}
})
最佳方式,在指令中使用$ parser。 我不打算重复@ pkozlowski.opensource提供的已经很好的答案,所以这里是链接:https://stackoverflow.com/a/14425022/215945
所有上述解决方案都涉及使用ng-model,这使得找不到this
。
使用ng-change会导致问题。见AngularJS - reset of $scope.value doesn't change value in template (random behavior)
答案 1 :(得分:64)
在文字字段中使用ng-pattern
:
<input type="text" ng-model="myText" name="inputName" ng-pattern="onlyNumbers">
然后将其包含在您的控制器上
$scope.onlyNumbers = /^\d+$/;
答案 2 :(得分:17)
所提出的解决方案都没有对我有用,几个小时后我终于找到了方法。
这是角度指令:
angular.module('app').directive('restrictTo', function() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var re = RegExp(attrs.restrictTo);
var exclude = /Backspace|Enter|Tab|Delete|Del|ArrowUp|Up|ArrowDown|Down|ArrowLeft|Left|ArrowRight|Right/;
element[0].addEventListener('keydown', function(event) {
if (!exclude.test(event.key) && !re.test(event.key)) {
event.preventDefault();
}
});
}
}
});
输入看起来像:
<input type="number" min="0" name="inputName" ng-model="myModel" restrict-to="[0-9]">
正则表达式评估按下的键,而不是值。
它也可以与输入type="number"
完美配合,因为它可以防止更改其值,因此密钥永远不会显示,也不会影响模型。
答案 3 :(得分:16)
这是我对@Mark Rajcok推荐的$parser
解决方案的最佳实施方法。它本质上是@ pkozlowski.opensource的excellent $parser for text answer但重写只允许数字。所有的功劳归功于他,这只是为了节省你5分钟阅读答案,然后重写你自己:
app.directive('numericOnly', function(){
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
var transformedInput = inputValue ? inputValue.replace(/[^\d.-]/g,'') : null;
if (transformedInput!=inputValue) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
};
});
你可以这样使用它:
<input type="text" name="number" ng-model="num_things" numeric-only>
有趣的是,空格永远不会到达解析器,除非被字母数字所包围,因此您必须根据需要.trim()
。此外,此解析器对<input type="number">
执行 NOT 工作。出于某种原因,非数字不会将它移到解除器的位置,但是它们做使它成为输入控件本身。
答案 4 :(得分:4)
有几种方法可以做到这一点。
您可以使用 class RecyclerTouchListener implements RecyclerView.OnItemTouchListener { //to intercept touch before RecyclerView picks up ACTION_UP or ACTION_DOWN
public ClickListener clickListener;
private GestureDetector gestureDetector;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final ClickListener clickListener) {
this.clickListener=clickListener;
gestureDetector=new GestureDetector(context,new GestureDetector.SimpleOnGestureListener(){
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child=recyclerView.findChildViewUnder(e.getX(),e.getY());
if(child!=null&&clickListener!=null){
clickListener.onLongClick(child,recyclerView.getChildAdapterPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child=rv.findChildViewUnder(e.getX(),e.getY());
if (child!=null&&clickListener!=null&&gestureDetector.onTouchEvent(e)){
clickListener.onClick(child,rv.getChildAdapterPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
}
public static interface ClickListener { //Interface to detect touch
public void onClick(View v, int position);
public void onLongClick(View v, int position);
}
:
type="number"
或者 - 我为此创建了一个可重用的directive,它使用正则表达式。
<强> HTML 强>
<input type="number" />
<强>的Javascript 强>
<div ng-app="myawesomeapp">
test: <input restrict-input="^[0-9-]*$" maxlength="20" type="text" class="test" />
</div>
答案 5 :(得分:2)
这是一个Plunker处理任何上述命题无法处理的情况 通过使用$ formatters和$ parsers管道并避免使用type =“number”
以下是问题/解决方案的解释(也可在Plunker中找到):
/*
*
* Limit input text for floating numbers.
* It does not display characters and can limit the Float value to X numbers of integers and X numbers of decimals.
* min and max attributes can be added. They can be Integers as well as Floating values.
*
* value needed | directive
* ------------------------------------
* 55 | max-integer="2"
* 55.55 | max-integer="4" decimal="2" (decimals are substracted from total length. Same logic as database NUMBER type)
*
*
* Input type="number" (HTML5)
*
* Browser compatibility for input type="number" :
* Chrome : - if first letter is a String : allows everything
* - if first letter is a Integer : allows [0-9] and "." and "e" (exponential)
* Firefox : allows everything
* Internet Explorer : allows everything
*
* Why you should not use input type="number" :
* When using input type="number" the $parser pipeline of ngModel controller won't be able to access NaN values.
* For example : viewValue = '1e' -> $parsers parameter value = "".
* This is because undefined values are not allowes by default (which can be changed, but better not do it)
* This makes it impossible to modify the view and model value; to get the view value, pop last character, apply to the view and return to the model.
*
* About the ngModel controller pipelines :
* view value -> $parsers -> model value
* model value -> $formatters -> view value
*
* About the $parsers pipeline :
* It is an array of functions executed in ascending order.
* When used with input type="number" :
* This array has 2 default functions, one of them transforms the datatype of the value from String to Number.
* To be able to change the value easier (substring), it is better to have access to a String rather than a Number.
* To access a String, the custom function added to the $parsers pipeline should be unshifted rather than pushed.
* Unshift gives the closest access to the view.
*
* About the $formatters pipeline :
* It is executed in descending order
* When used with input type="number"
* Default function transforms the value datatype from Number to String.
* To access a String, push to this pipeline. (push brings the function closest to the view value)
*
* The flow :
* When changing ngModel where the directive stands : (In this case only the view has to be changed. $parsers returns the changed model)
* -When the value do not has to be modified :
* $parsers -> $render();
* -When the value has to be modified :
* $parsers(view value) --(does view needs to be changed?) -> $render();
* | |
* | $setViewValue(changedViewValue)
* | |
* --<-------<---------<--------<------
*
* When changing ngModel where the directive does not stand :
* - When the value does not has to be modified :
* -$formatters(model value)-->-- view value
* -When the value has to be changed
* -$formatters(model vale)-->--(does the value has to be modified) -- (when loop $parsers loop is finished, return modified value)-->view value
* |
* $setViewValue(notChangedValue) giving back the non changed value allows the $parsers handle the 'bad' value
* | and avoids it to think the value did not changed
* Changed the model <----(the above $parsers loop occurs)
*
*/
答案 6 :(得分:1)
以上所有解决方案都很大,我想为此付出2美分。
我只检查输入的值是否为数字,并检查输入的值是否为空。
这是html:
<input type="text" ng-keypress="CheckNumber()"/>
这是JS:
$scope.CheckKey = function () {
if (isNaN(event.key) || event.key === ' ' || event.key === '') {
event.returnValue = '';
}
};
这很简单。
我相信这不会对Paste tho起作用,就这样就知道了。
对于粘贴,我认为您将需要使用onChange事件并解析整个字符串,这是另一种猛兽。这是专门用于键入的。
粘贴更新:只需添加此JS函数:
$scope.CheckPaste = function () {
var paste = event.clipboardData.getData('text');
if (isNaN(paste)) {
event.preventDefault();
return false;
}
};
然后html输入添加触发器:
<input type="text" ng-paste="CheckPaste()"/>
我希望这对o /
有帮助答案 7 :(得分:1)
DECIMAL
directive('decimal', function() {
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, element, attr, ctrl) {
function inputValue(val) {
if (val) {
var digits = val.replace(/[^0-9.]/g, '');
if (digits.split('.').length > 2) {
digits = digits.substring(0, digits.length - 1);
}
if (digits !== val) {
ctrl.$setViewValue(digits);
ctrl.$render();
}
return parseFloat(digits);
}
return "";
}
ctrl.$parsers.push(inputValue);
}
};
});
DIGITS
directive('entero', function() {
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, element, attr, ctrl) {
function inputValue(val) {
if (val) {
var value = val + ''; //convert to string
var digits = value.replace(/[^0-9]/g, '');
if (digits !== value) {
ctrl.$setViewValue(digits);
ctrl.$render();
}
return parseInt(digits);
}
return "";
}
ctrl.$parsers.push(inputValue);
}
};
});
答案 8 :(得分:0)
解决方案: 我在应用程序中为所有输入,数字,文本或任何内容制定了一条指令,因此您可以输入一个值并更改事件。 制作角度6
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
// tslint:disable-next-line:directive-selector
selector: 'input[inputType]'
})
export class InputTypeDirective {
constructor(private _el: ElementRef) {}
@Input() inputType: string;
// tipos: number, letter, cuit, tel
@HostListener('input', ['$event']) onInputChange(event) {
if (!event.data) {
return;
}
switch (this.inputType) {
case 'number': {
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(/[^0-9]*/g, '');
if (initalValue !== this._el.nativeElement.value) {
event.stopPropagation();
}
break;
}
case 'text': {
const result = event.data.match(/[^a-zA-Z Ññ]*/g);
if (result[0] !== '') {
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(
/[^a-zA-Z Ññ]*/g,
''
);
event.stopPropagation();
}
break;
}
case 'tel':
case 'cuit': {
const initalValue = this._el.nativeElement.value;
this._el.nativeElement.value = initalValue.replace(/[^0-9-]*/g, '');
if (initalValue !== this._el.nativeElement.value) {
event.stopPropagation();
}
}
}
}
}
HTML
<input matInput inputType="number" [formControlName]="field.name" [maxlength]="field.length" [placeholder]="field.label | translate" type="text" class="filter-input">
答案 9 :(得分:0)
尝试一下
<input ng-keypress="validation($event)">
function validation(event) {
var theEvent = event || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
var regex = /[0-9]|\./;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault();
}
}
答案 10 :(得分:0)
这是一个非常好的解决方案,只允许输入input
的数字:
<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
答案 11 :(得分:0)
<input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />
您可以使用仅限数字的属性。
答案 12 :(得分:0)
基本和干净的HTML方式
SELECT * FROM sys.fn_my_permissions('TEST', 'USER');
答案 13 :(得分:0)
您可能还想删除输入开头的0 ...我只是在上面的Mordred回答中添加了一个if块,因为我还无法发表评论......
({ function() { alert("Hello") } })
答案 14 :(得分:0)
我知道这是旧的,但我已经为此目的创建了一个指令,以防任何人寻找一个简单的解决方案。使用起来非常简单。
您可以查看here。
答案 15 :(得分:-1)
<input type="text" ng-model="employee.age" valid-input input-pattern="[^0-9]+" placeholder="Enter an age" />
<script>
var app = angular.module('app', []);
app.controller('dataCtrl', function($scope) {
});
app.directive('validInput', function() {
return {
require: '?ngModel',
scope: {
"inputPattern": '@'
},
link: function(scope, element, attrs, ngModelCtrl) {
var regexp = null;
if (scope.inputPattern !== undefined) {
regexp = new RegExp(scope.inputPattern, "g");
}
if(!ngModelCtrl) {
return;
}
ngModelCtrl.$parsers.push(function(val) {
if (regexp) {
var clean = val.replace(regexp, '');
if (val !== clean) {
ngModelCtrl.$setViewValue(clean);
ngModelCtrl.$render();
}
return clean;
}
else {
return val;
}
});
element.bind('keypress', function(event) {
if(event.keyCode === 32) {
event.preventDefault();
}
});
}
}}); </script>
答案 16 :(得分:-1)
我最终创建了上述代码的修改指令,以接受输入并动态更改格式......
.directive('numericOnly', function($filter) {
return {
require: 'ngModel',
link: function(scope, element, attrs, modelCtrl) {
element.bind('keyup', function (inputValue, e) {
var strinput = modelCtrl.$$rawModelValue;
//filter user input
var transformedInput = strinput ? strinput.replace(/[^,\d.-]/g,'') : null;
//remove trailing 0
if(transformedInput.charAt(0) <= '0'){
transformedInput = null;
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}else{
var decimalSplit = transformedInput.split(".")
var intPart = decimalSplit[0];
var decPart = decimalSplit[1];
//remove previously formated number
intPart = intPart.replace(/,/g, "");
//split whole number into array of 3 digits
if(intPart.length > 3){
var intDiv = Math.floor(intPart.length / 3);
var strfraction = [];
var i = intDiv,
j = 3;
while(intDiv > 0){
strfraction[intDiv] = intPart.slice(intPart.length-j,intPart.length - (j - 3));
j=j+3;
intDiv--;
}
var k = j-3;
if((intPart.length-k) > 0){
strfraction[0] = intPart.slice(0,intPart.length-k);
}
}
//join arrays
if(strfraction == undefined){ return;}
var currencyformat = strfraction.join(',');
//check for leading comma
if(currencyformat.charAt(0)==','){
currencyformat = currencyformat.slice(1);
}
if(decPart == undefined){
modelCtrl.$setViewValue(currencyformat);
modelCtrl.$render();
return;
}else{
currencyformat = currencyformat + "." + decPart.slice(0,2);
modelCtrl.$setViewValue(currencyformat);
modelCtrl.$render();
}
}
});
}
};
})