2012-12-02 66 views
11

我看到了這個解決方案http://jsfiddle.net/gronky/GnTDJ/,它的工作原理。也就是說,當你輸入25,將其推回建模爲0.25如何在最新的AngularJS上進行百分比格式化輸入?

HTML:

<script type="text/javascript" ng:autobind 
     src="http://code.angularjs.org/0.9.17/angular-0.9.17.js"></script> 
<script> 
function Main() { 
    this.var = '1.0000'; 
} 
</script> 
<div ng:controller="Main"> 
    <input type="text" name="var" ng:format="percent"> 
    <pre>var = {{var|json}}</pre> 
</div>​ 

的JavaScript:

angular.formatter('percent', { 
    parse: function(value) { 
    var m = value.match(/^(\d+)\/(\d+)/); 
    if (m != null) 
     return angular.filter.number(parseInt(m[1])/parseInt(m[2]), 2); 
    return angular.filter.number(parseFloat(value)/100, 2); 
    }, 
    format: function(value) { 
    return angular.filter.number(parseFloat(value)*100, 0); 
    }, 
}); 
​ 

我試圖使它在最新的AngularJS工作,這不是」雖然http://jsfiddle.net/TrJcB/已經工作了,也就是說,當你輸入25時,它也被推回爲25,它不會推入正確的0.25值來建模。

或者也許已經有一個百分比的內置格式化程序?我也想用貨幣格式化程序,或逗號分隔的數字。

回答

17

小提琴不適用於當前的Angular版本,因爲相當多的API已經改變。 angular.formatter不再可用,也不是angular.filter

現在寫的方法是使用指令並利用指令控制器上的$parser$formatter。所以,你的鏈接功能將類似於

link: function(scope, ele, attr, ctrl){ 
     ctrl.$parsers.unshift(
      function(viewValue){ 
       return $filter('number')(parseFloat(viewValue)/100, 2); 
      } 
     ); 
     ctrl.$formatters.unshift(
      function(modelValue){ 
       return $filter('number')(parseFloat(modelValue)*100, 2); 
      } 
     ); 
     } 

而且過濾器是通過$filter服務現在訪問。您可以在這裏找到的文檔:http://docs.angularjs.org/api/ng.filter:number

原始例如更新小提琴:http://jsfiddle.net/abhaga/DdeCZ/18/

貨幣濾波器在角已經可用:http://docs.angularjs.org/api/ng.filter:currency

+0

謝謝!關於第二次查詢,我正在尋找貨幣的輸入,即當鍵入輸入時,控件會自動輸入逗號(s)。也許我會從完成貨幣輸入的百分比開始。非常感謝! – Hao

+1

也許值得注意的是,如果一個位於另一個語言環境中,另一個格式化程序/解析器可以使另一個格式化程序要求的模型爲'undefined'(即:$ filter('number')'returns'「4,00'''一個''。「'小數點分隔符)。 – elbaid

+0

這是應該返回一個字符串,而不是一個十進制數?我怎麼能得到它返回一個小數? –

33

實現百分比過濾器的另一種方式(與角#作品〜1.2 ):

angular.module('moduleName') 
.filter('percentage', ['$filter', function($filter) { 
    return function(input, decimals) { 
     return $filter('number')(input*100, decimals)+'%'; 
    }; 
}]); 

如何使用它:

<span>{{someNumber | percentage:2}}</span> 
2

下面是一個完整的指令,它將解析,格式化並對輸入執行角驗證。 (測試對角1.2 & 1.3。)

我們使用這種方式,以便我們的數據模型可以用十進制表示法(0.7634)表示,但我們爲用戶提供了一種可讀的格式(76.34),並執行最大精度。請注意,該指令純粹涉及數字方面。我發現將模板中的'%'單獨插入到模板中更容易,而不是將其包括在此處。

它默認強制執行從-100到100的輸入值,但您可以使用attrs pct-minpct-max提供自己的界限。

'use strict'; 

angular.module('XLDirectives') 
    .directive('xlPercentage', function($filter) { 
    // A directive for both formatting and properly validating a percentage value. 
    // Assumes that our internal model is expressed as floats -1 to +1: .099 is 9.9% 
    // Formats display into percents 1-100, and parses user inputs down to the model. 
    // Parses user input as floats between 0 and 100 into floats less than 1. 
    // Validates user input to be within the range -100 to +100. 
    // Sets Angular $valid property accordingly on the ngModelController. 
    // If a `pct-max` or `pct-min` attribute is specified on the <input>, will use those bounds instead. 
    // If a `pct-decimals` attr present, will truncate inputs accordingly. 

    function outputFormatter(modelValue, decimals) { 
     var length = decimals || 2; 
     if (modelValue != null) { 
     return $filter('number')(parseFloat(modelValue) * 100, length); 
     } else { 
     return undefined; 
     } 
    }; 

    function inputParser(viewValue, decimals) { 
     var length = decimals || 4; 
     if (viewValue != null) { 
     return $filter('number')(parseFloat(viewValue)/100, length); 
     } else { 
     return undefined; 
     } 

    } 

    function isWithinBounds(value, upper, lower) { 
     if (value >= lower && value <= upper) { 
     return true; 
     } else { 
     return false; 
     } 
    } 

    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function postLink(scope, element, attrs, ctrl) { 
     ctrl.$parsers.unshift(function(viewValue) { 
      // confirm the input from the view contains numbers, before parsing 
      var numericStatus = viewValue.match(/(\d+)/), 
      min = parseFloat(attrs.pctMin) || -100, 
      max = parseFloat(attrs.pctMax) || 100, 
      decimals = parseFloat(attrs.pctDecimals) || 4, 
      bounded = isWithinBounds(viewValue, max, min); 
      if (numericStatus !== null && bounded) { 
      ctrl.$setValidity('percentage', true); 
      // round to max four digits after decimal 
      return inputParser(viewValue, decimals); 
      } else { 
      ctrl.$setValidity('percentage', false); 
      return undefined 
      } 
     }); 

     ctrl.$formatters.unshift(outputFormatter); 
     // we have to watch for changes, and run the formatter again afterwards 
     element.on('change', function(e) { 
      var element = e.target; 
      element.value = outputFormatter(ctrl.$modelValue, 2); 
     }); 
     } 
    }; 
    }); 


// REFS: 
// http://stackoverflow.com/questions/17344828/angularjs-should-i-use-a-filter-to-convert-integer-values-into-percentages 
// http://stackoverflow.com/questions/13668440/how-to-make-a-percent-formatted-input-work-on-latest-angularjs 
+1

注: attrs.pct分鐘應attrs.pctMin 和 attrs.pct-MAX應該是attrs.pctMax (編輯後提交) –

+1

@OlivierClément:您的評論(並試圖編輯)謝謝。我在這些改變中改進了這條生產指令,但忘了在這裏更新它。 – XML

0

我修改了abhaga的答案,允許。##和##輸入。在我看來,這是更多的用戶友好

link: function(scope, element, attr, ngModel) { 
      ngModel.$parsers.unshift(
       function(viewValue){ 
        var perc = parseFloat(viewValue); 
        if (perc<0 || perc>100 || !isFinite(perc)){ 
         return null; 
        } 
        if (perc>1 && perc<=100){ 
         return parseFloat($filter('number')(perc/100)); 
        } 
        return perc; 
       } 
      ); 
      ngModel.$formatters.unshift(
       function(modelValue){ 
        if(!isFinite(modelValue)){ 
         return ""; 
        } 
        return $filter('number')(parseFloat(modelValue)*100, 2); 
       } 
      ); 
     }