AngularJSのngChangeを使用して、ユーザーが入力に追加する文字を削除するカスタム関数をトリガーしています。
<input type="text" name="inputName" data-ng-change="numbersOnly()"/>
問題は、入力した文字を削除できるように、numbersOnly()
をトリガーした入力をターゲットにする必要があることです。私はグーグルで長く一生懸命に見てきたが、これに関して何も見つけられなかった。
私に何ができる?
簡単な方法、ユースケースで機能する場合は type = "number" を使用します。
<input type="number" ng-model="myText" name="inputName">
別の簡単な方法:ng-pattern は、フィールドで許可されるものを制限する正規表現を定義するためにも使用できます。 「フォームに関するクックブック」ページ も参照してください。
ハック? way、コントローラーのng-modelを$ watch:
<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変数を使用する必要があるため、this
を見つける必要がありません。
Ng-changeを使用すると問題が発生します。 AngularJS-$ scope.valueのリセットはテンプレートの値を変更しません(ランダムな動作) を参照してください
テキストフィールドでng-pattern
を使用する:
<input type="text" ng-model="myText" name="inputName" ng-pattern="onlyNumbers">
次に、これをコントローラーに含めます
$scope.onlyNumbers = /^\d+$/;
提案された解決策はどれも私にとってうまく機能せず、数時間後にようやく道を見つけました。
これはangularディレクティブです:
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"
でも完全に機能します。そのため、キーは表示されず、モデルに干渉しません。
@Mark Rajcokが最善の方法として推奨している$parser
ソリューションの実装を次に示します。基本的には@ pkozlowski.opensourceの テキスト回答用の優れた$ parser ですが、数値のみを許可するように書き直されています。すべての功績は彼に委ねられています。これは、その答えを読んでから自分の書き直しを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()
を使用する必要があります。また、このパーサーはNOT<input type="number">
で動作します。なんらかの理由で、非数値は削除されるパーサーには到達しませんが、doは入力コントロール自体に到達します。
これを行うにはいくつかの方法があります。
type="number"
を使用できます:
<input type="number" />
あるいは、正規表現を使用する再利用可能な directive を作成しました。
Html
<div ng-app="myawesomeapp">
test: <input restrict-input="^[0-9-]*$" maxlength="20" type="text" class="test" />
</div>
Javascript
;(function(){
var app = angular.module('myawesomeapp',[])
.directive('restrictInput', [function(){
return {
restrict: 'A',
link: function (scope, element, attrs) {
var ele = element[0];
var regex = RegExp(attrs.restrictInput);
var value = ele.value;
ele.addEventListener('keyup',function(e){
if (regex.test(ele.value)){
value = ele.value;
}else{
ele.value = value;
}
});
}
};
}]);
}());
ここに 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)
*
*/
上記のソリューションはすべて非常に大きいため、これに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 /
10進数
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);
}
};
});
数字
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);
}
};
});
基本的でクリーンなHTMLの方法
<input type="number" />
私はこれが古いことを知っていますが、誰かが簡単な解決策を探している場合に備えて、この目的のためのディレクティブを作成しました。非常に使いやすい。
こちら で確認できます。
<input type="text" name="profileChildCount" id="profileChildCount" ng-model="profile.ChildCount" numeric-only maxlength="1" />
数値のみの属性を使用できます。
これを試して、
<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();
}
}
input
に入力番号のみを許可するための非常に優れたソリューションを次に示します。
<input type="text" ng-model="myText" name="inputName" onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
解決策:アプリ内のすべての入力、数値、テキスト、または任意のディレクティブを作成します。これにより、値を入力してイベントを変更できます。 angular 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">
また、入力の先頭にある0を削除することもできます。コメントを作成できないため、上記のMordredの回答にifブロックを追加するだけです。
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();
}
//clear beginning 0
if(transformedInput == 0){
modelCtrl.$setViewValue(null);
modelCtrl.$render();
}
return transformedInput;
});
}
};
})