web-dev-qa-db-ja.com

Angular

通貨のフィールドをフィルタリングするためのディレクティブが必要なので、ユーザーは入力するだけで、小数が暗示されます。

ニーズ:

  1. 10進フィールドをユーザータイプとしてフォーマットします-

ユーザーが入力すると、100分の1から開始します。したがって、「4」と入力して「0.04」と表示し、「42」と入力して「0.42」と入力し、298023と入力して「2980.23」と表示します

  1. フィールドは数字でなければなりません
  2. ネガティブを許可する必要があります-
  3. 数値入力として0.00を許可
  4. 理想的にはtype = "number"を使用しますが、 "type = text"は問題ありません
  5. フィールドをクリアして空にすることができるはずです。

Ng-currencyフィルターは、これらの要件をそのまま満たしていません。私が何を意味するかを知るために、プランカーの振る舞いを見てください。

My First Plunker には `input = text 'があり、負の数を許可します。 1つの問題は、最初の数値として負の数値を入力できないことです。フィールドをクリアすると、「0.00」に戻りますが、完全にクリアされるはずです。

   app.directive('format', ['$filter', function ($filter) {
 return {
            require: 'ngModel', //there must be ng-model in the html
            link: function (scope, elem, attr, ctrl) {
                if (!ctrl) return;

                ctrl.$parsers.unshift(function (viewValue, modelValue) {
                    var plainNumber = viewValue.replace(/[^-+0-9]/g,'');
                    var newVal = plainNumber.charAt(plainNumber.length-1);
                    var positive = plainNumber.charAt(0) != '-';
                    if(isNaN(plainNumber.charAt(plainNumber.length-1))){
                      plainNumber = plainNumber.substr(0,plainNumber.length-1)
                    }
                    //use angular internal 'number' filter
                    plainNumber = $filter('number')(plainNumber / 100, 2).replace(/,/g, '');
                    if(positive && newVal == '-'){
                      plainNumber = '-' + plainNumber;
                    }
                    else if(!positive && newVal == '+'){
                      plainNumber = plainNumber.substr(1);
                    }
                    plainNumber.replace('.', ',');

                    //update the $viewValue
                    ctrl.$setViewValue(plainNumber);
                    //reflect on the DOM element
                    ctrl.$render();
                    //return the modified value to next parser
                    return plainNumber;
                });
            }
        };

}]);

私の セカンドプランカーinput = textそして負の入力を可能にします。最初のプランカーと同様に、数字を入力した後でのみ、最初の文字としてネガを使用することはできません。 2つ目は、100分の1ではなく10分の1から始まることです。 (「3」と入力すると「0.03」と表示されますが、ここでは「0.3」と表示されます)

app.directive('inputRestrictor', [function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModelCtrl) {
            var pattern = /[^.0-9+-]/g;

            function fromUser(text) {
                if (!text)
                return text;

                var rep = /[+]/g;
                var rem = /[-]/g;
                rep.exec(text);
                rem.exec(text);

                var indexp = rep.lastIndex;
                var indexm = rem.lastIndex;
                text = text.replace(/[+.-]/g, '');
                if (indexp > 0 || indexm > 0) {
                    if (indexp > indexm) text = "+" + text; // plus sign?
                    else text = "-" + text;
                }

                var transformedInput = text.replace(pattern, '');
                transformedInput = transformedInput.replace(/([0-9]{1,2}$)/, ".$1")
                ngModelCtrl.$setViewValue(transformedInput);
                ngModelCtrl.$render();
                return transformedInput;
            }

            ngModelCtrl.$parsers.Push(fromUser);
        }
    };
}]);

これらのソリューションを調整したり、要件を満たすように調整したりするにはどうすればよいですか?余分なライブラリやアドオンは避けたいです。通貨フィルターのソースを調べて、追加の要件でそのフィルターを再作成するのが最善のアプローチだと言われています。これを実行したいのですが、現時点では実際にはそのスキルがありません。これらの2つのディレクティブは私が持っているものです。

12
jenryb

。::回答を更新-7月14日::。


この単純なディレクティブを確認してください。

app.directive('price', [function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            attrs.$set('ngTrim', "false");

            var formatter = function(str, isNum) {
                str = String( Number(str || 0) / (isNum?1:100) );
                str = (str=='0'?'0.0':str).split('.');
                str[1] = str[1] || '0';
                return str[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') + '.' + (str[1].length==1?str[1]+'0':str[1]);
            }
            var updateView = function(val) {
                scope.$applyAsync(function () {
                    ngModel.$setViewValue(val || '');
                    ngModel.$render();
                });
            }
            var parseNumber = function(val) {
                var modelString = formatter(ngModel.$modelValue, true);
                var sign = {
                    pos: /[+]/.test(val),
                    neg: /[-]/.test(val)
                }
                sign.has = sign.pos || sign.neg;
                sign.both = sign.pos && sign.neg;

                if (!val || sign.has && val.length==1 || ngModel.$modelValue && Number(val)===0) {
                    var newVal = (!val || ngModel.$modelValue && Number()===0?'':val);
                    if (ngModel.$modelValue !== newVal)
                        updateView(newVal);

                    return '';
                }
                else {
                    var valString = String(val || '');
                    var newSign = (sign.both && ngModel.$modelValue>=0 || !sign.both && sign.neg?'-':'');
                    var newVal = valString.replace(/[^0-9]/g,'');
                    var viewVal = newSign + formatter(angular.copy(newVal));

                    if (modelString !== valString)
                        updateView(viewVal);

                    return (Number(newSign + newVal) / 100) || 0;
                }
            }
            var formatNumber = function(val) {
                if (val) {
                    var str = String(val).split('.');
                    str[1] = str[1] || '0';
                    val = str[0] + '.' + (str[1].length==1?str[1]+'0':str[1]);
                }
                return parseNumber(val);
            }

            ngModel.$parsers.Push(parseNumber);
            ngModel.$formatters.Push(formatNumber);
        }
    };
}]);

そして、次のように使用します。

<input type="text" ng-model="number" price >

このライブをご覧ください [〜#〜]プランカー[〜#〜] (7月14日)

8
MeTe-30

私はこれがあなたの要件を完全に満たすことができると思います

https://github.com/FCSAmerica/angular-fcsa-number

デフォルトで小数の数値のみを許可する入力を制限できますangular入力検証またはcharコードを使用します。

3
Sa E Chowdary

Angular Numeric

Angular Numericは、完全な数値入力フィールドを実装する高度なディレクティブです。

使い方はとても簡単ですが、パワフルです。

<input numeric min="-20" max="100" decimals="3" />

最小値と最大値のチェックがあります。値が最小値を下回ると、値は最小値に設定されます。値が最大値を超えると、値が最大値に設定されます。

フォーマットはblurイベントで行われます。千の区切り文字と小数は、現在のAngularロケールに基づいています。

小数点以下の桁数を設定できます。

https://www.npmjs.com/package/angular-numeric-directive

1
Charlie